如何组织大猩猩mux路线?

zol*_*ola 10 go gorilla

我正在使用Gorilla Mux编写REST API,我在组织路由时遇到问题,目前我的所有路由都在这样的main.go文件中定义

//main.go
package main

import (
    "NovAPI/routes"
    "fmt"
    "github.com/gorilla/mux"
    "net/http"
)

func main() {

    router := mux.NewRouter().StrictSlash(true)

    router.HandleFunc("/hello", func(res http.ResponseWriter, req *http.Request) {
        fmt.Fprintln(res, "Hello")
    })

    router.HandleFunc("/user", func(res http.ResponseWriter, req *http.Request) {
        fmt.Fprintln(res, "User")
    })

    router.HandleFunc("/route2", func(res http.ResponseWriter, req *http.Request) {
        fmt.Fprintln(res, "Route2")
    })

    router.HandleFunc("/route3", func(res http.ResponseWriter, req *http.Request) {
        fmt.Fprintln(res, "Route3")
    })

    // route declarations continue like this

    http.ListenAndServe(":1128", router)

}
Run Code Online (Sandbox Code Playgroud)

所以我想要做的是取出并将这个路由声明拆分成多个文件,我将如何去做呢?提前致谢.

Lor*_*ris 10

您可以将路由器独立地模块化为不同的软件包,然后将其安装在主路由器上

在以下问题上仅作一些详细说明,您可以提出这种方法,使其具有相当的可扩展性(在某种程度上更易于测试)

/api/router.go

package api

import (
    "net/http"

    "github.com/gorilla/mux"
)

func Router() *mux.Router {
    router := mux.NewRouter()
    router.HandleFunc("/", home)
    return router
}

func home(w http.ResponseWriter, req *http.Request) {
    w.Write([]byte("hello from API"))
}
Run Code Online (Sandbox Code Playgroud)

/main.go

package main

import (
    "log"
    "net/http"
    "strings"

    "github.com/...yourPath.../api"
    "github.com/...yourPath.../user"
    "github.com/gorilla/mux"
)

func main() {
    router := mux.NewRouter()

    router.HandleFunc("/", home)
    mount(router, "/api", api.Router())
    mount(router, "/user", user.Router())

    log.Fatal(http.ListenAndServe(":8080", router))
}

func mount(r *mux.Router, path string, handler http.Handler) {
    r.PathPrefix(path).Handler(
        http.StripPrefix(
            strings.TrimSuffix(path, "/"),
            handler,
        ),
    )
}

func home(w http.ResponseWriter, req *http.Request) {
    w.Write([]byte("Home"))
}
Run Code Online (Sandbox Code Playgroud)


Elw*_*nar 9

这样的事情怎么样?

//main.go
package main

import (
    "NovAPI/routes"
    "fmt"
    "github.com/gorilla/mux"
    "net/http"
)

func main() {

    router := mux.NewRouter().StrictSlash(true)

    router.HandleFunc("/hello", HelloHandler)
    router.HandleFunc("/user", UserHandler)
    router.HandleFunc("/route2", Route2Handler)
    router.HandleFunc("/route3", Route3Handler)
    // route declarations continue like this

    http.ListenAndServe(":1128", router)

}

func HelloHandler(res http.ResponseWriter, req *http.Request) {
    fmt.Fprintln(res, "Hello")
}

func UserHandler(res http.ResponseWriter, req *http.Request) {
    fmt.Fprintln(res, "User")
}

func Route2Handler(res http.ResponseWriter, req *http.Request) {
    fmt.Fprintln(res, "Route2")
}

func Route3Handler(res http.ResponseWriter, req *http.Request) {
    fmt.Fprintln(res, "Route3")
}
Run Code Online (Sandbox Code Playgroud)

这样您就可以将处理程序放在其他文件中,甚至是其他包中.

如果你最终使用像数据库这样的附加依赖项,你甚至可以使用构造函数技巧来避免使用全局变量:

//main.go

func main() {
    db := sql.Open(…)

    //...

    router.HandleFunc("/hello", NewHelloHandler(db))

    //...
}

func NewHelloHandler(db *sql.DB) func(http.ResponseWriter, *http.Request) {
    return func(res http.ResponseWriter, req *http.Request) {
        // db is in the local scope, and you can even inject it to test your
        // handler
        fmt.Fprintln(res, "Hello")
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我不明白这一点:无论哪种方式,你仍然要在某处编写你的路线...如果你的"主"太长,也许你可以编写一个`NewRouter`帮助器来为你初始化它. (2认同)

abm*_*abm 6

我喜欢查看 github 中的其他项目以获取有关如何做事的想法,对于这些情况,我通常首先查看Docker repo。他们的做法是这样的:

对于系统的路由,在system_routes.go 中定义所有处理程序,然后在system.go 中的 NewRouter 函数上初始化这些路由。

type systemRouter struct {
    backend Backend
    routes  []router.Route
}

func NewRouter(b Backend) router.Router {
    r := &systemRouter{
        backend: b,
    }

    r.routes = []router.Route{
        local.NewOptionsRoute("/", optionsHandler),
        local.NewGetRoute("/_ping", pingHandler),
        local.NewGetRoute("/events", r.getEvents),
        local.NewGetRoute("/info", r.getInfo),
        local.NewGetRoute("/version", r.getVersion),
        local.NewPostRoute("/auth", r.postAuth),
    }

    return r
}

// Routes return all the API routes dedicated to the docker system.
func (s *systemRouter) Routes() []router.Route {
    return s.routes
}
Run Code Online (Sandbox Code Playgroud)

请注意,systemRouter 实现了router.Router接口,Routes 函数返回一个 []router.Route,它们的处理程序定义为

func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error
Run Code Online (Sandbox Code Playgroud)

而不是 Go 的标准 http 处理程序:

func(w http.ResponseWriter, r *http.Request)
Run Code Online (Sandbox Code Playgroud)

所以他们有额外的代码可以在makeHttpHandler函数中将Docker API 处理程序转换为 Go HTTP 处理程序

最后,为了将这些路由添加到他们的 mux 路由器,在他们的server.go 上,他们实现了其他几个功能来将中间件添加到他们的处理程序中。

如果您认为这是您正在寻找的东西,那么请花点时间分析 Docker 代码的路线,如果您需要我详细说明或遗漏任何内容,请发表评论。