I'm reading "The Way to Go" book and while I understand most, I'm having a difficulty with the following.
The author mentions a way to wrap a HandleFunc in a closure that takes care of panics like so:
func Index(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "text/html")
fmt.Fprint(w, "<h2>Index</h2>")
}
func logPanics(function HandleFunc) HandleFunc {
return func(w http.ResponseWriter, req *http.Request) {
defer func() {
if err := recover(); err != nil {
log.Printf("[%v] caught panic: %v", req.RemoteAddr, err)
}
}()
function(w, req) // Where do w and req come from?
}
}
Later on this is invoked via:
http.HandleFunc("/", logPanics(Index))
I understand most of it, but wonder how w and req used in
function(w, req)
get their values? Do I understand correctly, that the w and req in the return statement
return func(w http.ResponseWriter, req *http.Request)
are completely different? Then I wonder, how do w and req get their values. I hope somebody can shed some light on my question as I really want to understand what's going on instead of just copying and pasting.
When you call http.HandleFunc(path, function)
, it causes the server to invoke function
when a request is received for the given path. The function is called with a *http.Request
describing the request from the client and a http.ResponseWriter
that can be used to write a response back to the client.
In the following call:
http.HandleFunc("/", logPanics(Index))
The handler function being registered is the function returned by logPanics
. When a request for /
is received, that function will be called. That function in turn calls your Index
function and traps any panics.
Do I understand correctly, that the w and req in the return statement
return func(w http.ResponseWriter, req *http.Request)
are completely different?
No, not at all, these are the same! Once you delete the defer and assign the closure to a variable it becomes a bit clearer:
func logPanics(function HandleFunc) HandleFunc {
f := func(w http.ResponseWriter, req *http.Request) {
function(w, req) // Where do w and req come from?
}
return f
}
No this code does nothing at all but it is easy to see what goes on: 1) f
is a function with the proper signature (taking a ResponseWriter and a Request). 2) All it does is call the function passed to logPanics
with the argument it was called. 3) This function f
is returned.