我有一个像这样的处理程序:
type handler struct {
Services *domain.Services
Config *domain.Config
}
然后,很多新类型(它们可能是二十个或更多),如下所示:
type Handler1 handler
type Handler2 handler
每个人都有一个ServeHTTP
方法。我使用它,以便他们可以访问服务和配置变量。
他们正在这样的路线中使用:
r.Handle("/login", &h.Handler1{
Services: s,
Config: c,
})
我的问题是:我应该创建所有这些结构还是只创建一个将Services和Config注入请求Context的函数,然后使用r.Context().Value()
访问它们?
我想过这样做:
func handler1(w http.ResponseWriter, r *http.Request) {
s, c := r.Context().Value("services"), r.Context().Value("config")
// My code
}
r.HandleFunc("/login", inject(handler1, s, c))
什么是最好的/推荐的?
答案 0 :(得分:2)
作为创建所有这些处理程序类型的替代方法,您可以使用返回其他函数的函数(http.HandlerFunc)。这样,您将创建一个闭包,并在请求到达处理程序时访问参数。例如:
package main
import (
"fmt"
"net/http"
)
func SomeHandler(conf SomeConfig, service SomeService) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "foobar config: %q", conf)
}
}
func main() {
// TODO: initialise your conf & service
http.HandleFunc("/somepath", SomeHandler(conf, service))
}
答案 1 :(得分:0)
您可能会创建某种路由器,它将提供ServeHTTP并在您的真实处理程序和路径路径之间进行映射。
这样的事情:
package main
import "net/http"
type Router struct {
routes map[string]func(rw http.ResponseWriter, r *http.Request)
}
func NewRouter() *Router {
var r Router
r.routes = make(map[string]func(rw http.ResponseWriter, r *http.Request))
return &r
}
func (router *Router) addRoute(path string, f func(rw http.ResponseWriter, r *http.Request)) {
router.routes[path] = f
}
func (router *Router) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
for route, serveHTTP := range router.routes {
if route == r.URL.Path {
serveHTTP(rw, r)
return
}
}
rw.WriteHeader(http.StatusNotFound)
}
func teapot(rw http.ResponseWriter, r *http.Request) {
rw.WriteHeader(http.StatusTeapot)
}
func ok(rw http.ResponseWriter, r *http.Request) {
rw.WriteHeader(http.StatusOK)
}
func main() {
r := NewRouter()
r.addRoute("/teapot", teapot)
r.addRoute("/ok", ok)
http.ListenAndServe("localhost:8080", r)
}