使用中间处理程序功能路由请求

时间:2018-07-09 20:38:24

标签: go

我正在考虑使用标准库进行路由的方法。具有根据请求类型调用其他处理程序功能的处理程序功能是否有效?例如

func main() {
    m := http.NewServeMux()
    m.HandleFunc("/books", books)
    // ...
}

func books(w http.ResponseWriter, r *http.Request) {
    switch r.Method {
        case "GET":
            getBooks(w, r)
        case "POST":
            createBook(w, r)
    }
}

这是好习惯吗?我不想声明自定义处理程序,因为我发现函数要干净一些。

3 个答案:

答案 0 :(得分:5)

是的,这是完全正确的;处理程序只是函数,因此没有理由不应该这样做。实际上,middleware is usually implemented就是这样。

关于处理程序功能根本没有“魔术”。只要您要写入正确的文件描述符(w http.ResponseWriter),一切都会发生。

这并不意味着对于所有应用程序而言,使用此模式不一定是个好主意-路由库的存在是有原因的-但对于较小的程序,它就可以正常工作。

答案 1 :(得分:3)

  

HandlerFunc呼叫另一个HandlerFunc是完全有效的。

实际上,这就是使用标准库实现中间件的方式。

这是 Mat Ryer Post(令人惊讶的家伙btw),他进一步详细解释了他所说的
“ http.Handler包装器技术”

您想要使用HandlerFunc的方式使我想起Laravel's Resource Controllers,我认为它非常简洁。但是,不小心使用它们可能会成为不必要的开销。

我建议您尝试一下julienschmidt/httprouter库。
它非常快速且易于使用。

答案 2 :(得分:2)

这是有效的,正如其他答案处理程序中提到的那样,它们只是函数。

改变的是请求方法;可能值得考虑使用地图实现。随着您需要更改处理程序的数量,这可能会更具扩展性。

type BookController struct {
    routes map[string]http.HandlerFunc
}

func (b BookController) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    // beware this very basic example will panic if there's not a registered handler for r.Method
    // but I assume you'd have to do handling of missing method logic in your default switch anyway
    b.routes[r.Method].ServeHTTP(w, r)
}

并注册它们:

m := http.NewServeMux()
b := BookController{}
b.routes = map[string]http.HandlerFunc{
    "GET": getBooks,
    "POST": createBooks,
}
m.Handle("/books", b)

稍微多一些样板,但以后可以更轻松地添加/删除处理程序。