-1

我有这个实用程序:

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)

?

4

1 回答 1

4

http.HandlerFunc一个类型表示func(ResponseWriter, *Request)

http.HandlerFunc和之间的区别func(ResponseWriter, *Request)是:http.HandlerFunc类型有方法调用ServeHTTP()

源代码

// 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.HandlerFunchas 方法。.ServeHTTP()http.Handler


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

因为要继续处理传入的请求,您需要调用.ServeHTTP().

于 2018-12-02T05:25:12.520 回答