Go:使用不同的处理程序或将变量注入请求上下文?

时间:2016-11-14 23:48:26

标签: http go request

我有一个像这样的处理程序:

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

什么是最好的/推荐的?

2 个答案:

答案 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)
}