I am learning Go and at the moment trying to understand what and how actually julienschmidt's httprouterhttp router works. Especially how the router.HandlerFunc() works.
Go's http package:
http.Handler: Handler is an Interface. Any type which has the same method signature i.e., ServeHTTP(w,r) implements a Handler.http.Handle: http.Handle is a function which has two parameters. 1) String to match request path, 2)Handler, to call its ServeHTTP() method.http.HandlerFunc: A custom function type with function signature (ResponseWriter, *Request) and its own ServeHTTP(w,r) method, which satisfies as a http.Handler interface.
Now if I need to use a function eg. Bar(ResponseWriter, *Request) which satisfies to be a HandlerFunc, inside http.Handle, I type caste/covert the function to http.HandlerFunc and then use it inside the http.Handle. Like so:
func Bar(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("My bar func response"))
}
...
mf := http.HandlerFunc(Bar)
http.Handle("/path", mf)
- Looking at the http.HandleFunc source code, this is how http.HandleFunc() works. It expects a function which as the signature of (w ResponseWriter, r *Request) and type caste the function.
Like so:
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
if handler == nil {
panic("http: nil handler")
}
mux.Handle(pattern, HandlerFunc(handler))
}
julienschmidt's httprouterhttp
Looking at the source code of router.HandlerFunc()
func (r *Router) HandlerFunc(method, path string, handler http.HandlerFunc) {
r.Handler(method, path, handler)
}
- Instead of expecting a function with appropriate signature (ResponseWriter, *Request) like the http.HandleFunc(), it expects a http.HandlerFunc.
- Also without type casting/converting the function to a HandlerFunc type, it just pass the function to another function router.Handler(method, path string, handler http.Handler), which again expects a Handler.
So I can execute this code without any problem:
router.HandlerFunc(http.MethodPost, "/path", Bar) // Bar is not type casted/converted to a HandlerFunc
I can understand type casting the Bar to a HandlerFunc and then pass it to router.HandlerFunc().
Could you please clear some of my doubts:
- How does without type casting the Bar() to a HandlerFunc satisfies as a HandlerFunc type to the router.HandlerFunc()?
- If the router.Handler() expects a http.Handler type, how come Bar() without type casting to the http.HandlerFunc satisfies a a Handler to the router.Handler()?
- What am I missing?