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

how to build own simple router in golang?

我正在 golang 中构建自己的路由器以理解逻辑,但是我收到 404 错误,通常找不到,我可以 运行 服务器,但我在 hello[=14= 中编写了函数]名字,不是运行。这是什么原因?

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")
}

您有全局变量 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")
}

您的主函数使用 := 表示法声明并初始化一个名为 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,
    }

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

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