如何在golang中构建自己的简单路由器?

时间:2016-10-16 12:19:30

标签: go router httpserver

我在golang中构建自己的路由器以理解逻辑,但是我发现404错误没有找到正常,我能够运行到服务器但是我用 hello 名称编写了函数,它没有运行。这可能是什么原因?

package main
import (
    "fmt"
    "log"
    "net/http"
    "strings"
    "time"
)

var Session *http.Server
var r Router

func Run(port string) {
    Session = &http.Server{
        Addr:           port,
        Handler:        &r,
        ReadTimeout:    10 * time.Second,
        WriteTimeout:   10 * time.Second,
        MaxHeaderBytes: 1 << 20,
    }
    log.Fatal(Session.ListenAndServe())
}

type Handle func(http.ResponseWriter, *http.Request)

type Router struct {
    mux map[string]Handle
}

func newRouter() *Router {
    return &Router{
        mux: make(map[string]Handle),
    }
}

func (r *Router) Add(path string, handle Handle) {
    r.mux[path] = handle
}

func GetHeader(url string) string {
    sl := strings.Split(url, "/")
    return fmt.Sprintf("/%s", sl[1])
}

func (rt *Router) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    head := GetHeader(r.URL.Path)
    h, ok := rt.mux[head]
    if ok {
        h(w, r)
        return
    }
    http.NotFound(w, r)
}

func hello(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "%s", "hello world")
}

func main() {
    r := newRouter()
    r.Add("/hello", hello)
    Run(":8080")
}

2 个答案:

答案 0 :(得分:5)

您的主要功能是使用<!doctype html><html> <head> <meta http-equiv=""X-UA-Compatible"" content=""IE=edge""/> </head><body> <style> .video-container { position:relative; padding-bottom:56.25%; padding-top:30px; height:0; overflow:hidden; } .video-container iframe, .video-container object, .video-container embed { position:absolute; top:0; left:0; width:100%; height:100%; } } </style> <div class="video-container"> <div id="player"></div> </div> <script> var tag = document.createElement('script'); tag.src = "https://www.youtube.com/iframe_api"; var firstScriptTag = document.getElementsByTagName('script')[0]; firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); var player; function onYouTubeIframeAPIReady() { player = new YT.Player('player', { width: '640', height: '390', videoId: 'jhFDyDgMVUI', playerVars: { autohide: 1, showinfo: 0 , html5: 1, enablejsapi: 1, autoplay: 1, origin: 'http://www.example.co'}, events: { 'onReady': onPlayerReady, 'onStateChange': onPlayerStateChange } }); alert('apirdy'); } function onPlayerReady(event) { event.target.playVideo(); alert('onrdy'); player.addEventListener('onStateChange', onPlayerStateChange); } function onPlayerStateChange(event) { alert('onchange'); } </script> </body></html> 表示法,声明并初始化一个名为r的新局部变量,其范围与您在列表顶部的全局变量不同。

这意味着您要添加处理程序的:=变量不是您尝试分配给r结构的全局变量,因此您的Http.Server根本找不到任何映射到它自己的接收器ServeHTTP

解决方案是将r声明为指向r Router的指针,如下所示:

Router

并且在你的处理程序中,你可以直接传递指针而不需要任何解除引用:

var r *Router

当然,请记住通过指定指针值来初始化变量,而不是声明一个新的本地变量:

Session = &http.Server{
        Addr:           port,
        Handler:        r,
        ReadTimeout:    10 * time.Second,
        WriteTimeout:   10 * time.Second,
        MaxHeaderBytes: 1 << 20,
    }

答案 1 :(得分:0)

你有全局变量var r Router但是在func main()内你创建了另一个,本地变量和路径恰好只添加到它:

 func main() {
        r := newRouter()
        r.Add("/hello", hello)
        Run(":8080")
    }

只需调整

即可
var r =&Router{}

func Run(port string) {
    Session = &http.Server{
        Addr:           port,
        Handler:        r,
        ReadTimeout:    10 * time.Second,
        WriteTimeout:   10 * time.Second,
        MaxHeaderBytes: 1 << 20,
    }
    log.Fatal(Session.ListenAndServe())
}
func main() {
    r = newRouter()
    r.Add("/hello", hello)
    Run(":8080")
}