serveHTTP实用程序从哪里来?

时间:2018-12-02 05:15:59

标签: go go-http

我有这个实用程序:

type Handler struct{}

func (h Handler) Mount(router *mux.Router, v PeopleInjection) {
    router.HandleFunc("/api/v1/people", h.makeGetMany(v)).Methods("GET")
}

以上称为:

func (h Handler) makeGetMany(v PeopleInjection) http.HandlerFunc {

    type RespBody struct {}

    type ReqBody struct {
        Handle string
    }

    return tc.ExtractType(
        tc.TypeList{ReqBody{},RespBody{}},
        func(w http.ResponseWriter, r *http.Request) {
         // ...
    })
}

然后tc.ExtractType就像这样:

func ExtractType(s TypeList, h http.HandlerFunc) http.HandlerFunc {

    return func(w http.ResponseWriter, r *http.Request) {

        h.ServeHTTP(w, r)  // <<< h is just a func right? so where does ServeHTTP come from?
    }
}

我的问题是-serveHTTP方法/功能从哪里来?

不仅仅是h参数只是具有以下签名的功能:

func(w http.ResponseWriter, r *http.Request) { ... }

那么该函子如何附加了ServeHTTP函子?

换句话说,我为什么打电话

h.ServeHTTP(w,r)

代替

h(w,r)

1 个答案:

答案 0 :(得分:5)

http.HandlerFunc是代表func(ResponseWriter, *Request)的类型。

http.HandlerFuncfunc(ResponseWriter, *Request)之间的区别是:http.HandlerFunc类型的方法称为ServeHTTP()

来自source code

// The HandlerFunc type is an adapter to allow the use of
// ordinary functions as HTTP handlers. If f is a function
// with the appropriate signature, HandlerFunc(f) is a
// Handler that calls f.
type HandlerFunc func(ResponseWriter, *Request)

// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
    f(w, r)
}

http.HandlerFunc()可用于包装处理程序函数。

func Something(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // do something

        next.ServeHTTP(w, r)
    })
}

包装的处理程序将具有http.HandlerFunc()类型,这意味着我们将能够访问它的.ServeHTTP()方法。


还有另一种类型,称为http.Handler的接口。它具有.ServeHTTP()方法签名,并且必须在嵌入接口的结构上实现。

type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}

正如您在上面的Something()函数中所看到的那样,必须使用http.Handler类型的返回值,但是我们返回了包装在http.HandlerFunc()中的处理程序。很好,因为http.HandlerFunc的方法.ServeHTTP()满足http.Handler接口的要求。


  

换句话说,为什么我打电话给h.ServeHTTP(w,r)而不是h(w,r)

由于要继续处理传入的请求,您需要致电.ServeHTTP()