如何组织大猩猩多路复用器路线?
how to organize gorilla mux routes?
我正在使用 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)
}
所以我想做的是取出这个路由声明并将其拆分成多个文件,我该怎么做呢? 提前致谢。
这样的事情怎么样?
//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")
}
这样您就可以将处理程序放在其他文件中,甚至其他包中。
如果你最终有额外的依赖关系,比如数据库,你甚至可以使用构造函数技巧避免对全局变量的需要:
//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")
}
}
我喜欢查看 github 中的其他项目以获取有关如何做事的想法,对于这些情况,我通常会先查看 Docker repo。他们是这样做的:
为system's routes, define all handlers in system_routes.go and then initialize those routes on a NewRouter function in system.go.
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
}
注意systemRouter实现了router.Router接口和Routes函数returns一个[]router.Route,它们的handlers定义为
func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error
代替 Go 的标准 http 处理程序:
func(w http.ResponseWriter, r *http.Request)
所以他们有额外的代码在 makeHttpHandler 函数中将 Docker API 处理程序转换为 Go HTTP 处理程序。
最后,将这些路由添加到他们的 mux 路由器,在他们的 server.go they implement several other functions to add middleware 上添加到他们的处理程序。
如果您认为这是您要找的东西,请花点时间分析他们路线的 Docker 代码,如果您需要我详细说明或者我遗漏了什么, post 评论。
您可以将您的路由器独立模块化成不同的包,挂载在主路由器上
稍微详细说明以下 issue,您可以想出这种方法,这使得它具有相当大的可扩展性(并且在某种程度上更容易测试)
/api/router.去
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"))
}
/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"))
}
我正在使用 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)
}
所以我想做的是取出这个路由声明并将其拆分成多个文件,我该怎么做呢? 提前致谢。
这样的事情怎么样?
//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")
}
这样您就可以将处理程序放在其他文件中,甚至其他包中。
如果你最终有额外的依赖关系,比如数据库,你甚至可以使用构造函数技巧避免对全局变量的需要:
//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")
}
}
我喜欢查看 github 中的其他项目以获取有关如何做事的想法,对于这些情况,我通常会先查看 Docker repo。他们是这样做的:
为system's routes, define all handlers in system_routes.go and then initialize those routes on a NewRouter function in system.go.
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
}
注意systemRouter实现了router.Router接口和Routes函数returns一个[]router.Route,它们的handlers定义为
func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error
代替 Go 的标准 http 处理程序:
func(w http.ResponseWriter, r *http.Request)
所以他们有额外的代码在 makeHttpHandler 函数中将 Docker API 处理程序转换为 Go HTTP 处理程序。
最后,将这些路由添加到他们的 mux 路由器,在他们的 server.go they implement several other functions to add middleware 上添加到他们的处理程序。
如果您认为这是您要找的东西,请花点时间分析他们路线的 Docker 代码,如果您需要我详细说明或者我遗漏了什么, post 评论。
您可以将您的路由器独立模块化成不同的包,挂载在主路由器上
稍微详细说明以下 issue,您可以想出这种方法,这使得它具有相当大的可扩展性(并且在某种程度上更容易测试)
/api/router.去
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"))
}
/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"))
}