问题
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 ofh(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