Where does the serveHTTP utility come from on supposedly naked func

∥☆過路亽.° 提交于 2019-12-13 08:09:19

问题


I have this utility:

type Handler struct{}

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

the above calls this:

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) {
         // ...
    })
}

and then tc.ExtractType is like so:

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?
    }
}

my question is - where does the serveHTTP method/func come from??

isn't the h parameter just a func with this signature:

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

so then how does that func have the ServeHTTP func attached to it?

In other words, why I am I calling

h.ServeHTTP(w,r)

instead of

h(w,r)

?


回答1:


The http.HandlerFunc is a type represent func(ResponseWriter, *Request).

The difference between http.HandlerFunc and func(ResponseWriter, *Request) is: http.HandlerFunc type has method called ServeHTTP().

From the 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)
}

The http.HandlerFunc() can be used to wrap handler function.

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

        next.ServeHTTP(w, r)
    })
}

The wrapped handler will have http.HandlerFunc() type, meaning we'll be able to access it's .ServeHTTP() method.


There is also another type, an interface called http.Handler. It has .ServeHTTP() method signature, and it must be implemented on the struct where the interface is being embedded.

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

As you can see on Something() function above, a return value in http.Handler type is required, but we returned a handler wrapped in http.HandlerFunc(). It's fine, because the http.HandlerFunc has method .ServeHTTP() who fulfil the requirement of http.Handler interface.


In other words, why I am I calling h.ServeHTTP(w,r) instead of h(w,r)?

Because to continue serve the incoming request, you need to call .ServeHTTP().



来源:https://stackoverflow.com/questions/53577614/where-does-the-servehttp-utility-come-from-on-supposedly-naked-func

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!