The Difference Between Handler and HandlerFunc
Confused by seeing references to Handler
and HandlerFunc
in Go code?
Here is all you need to know to understand how they relate to each other and which one to use.
Handler
Handler
is an interface. You can see the complete definition in the documentation:
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
Whatever provides a ServeHTTP
function satisfies the Handler
interface!
To satisfy this interface, you could write your own struct which has the function signature required. It could look like this:
type MyHandler struct {
// whatever you need here
}
func (h *MyHandler) ServeHTTP(ResponseWriter, *Request) {
// your handler code
}
This would work! But if you would be creating an empty struct anyway, there is a way to skip writing unnecessary code: with HandlerFunc.
HandlerFunc Is a Shortcut
HandlerFunc
is a type, defined in the same http package.
The docs describe it, but the code makes it clearer
Here is what it looks like:
type HandlerFunc func(ResponseWriter, *Request)
// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
This type, makes it possible to turn a simple function into a Handler interface satisfying value. It’s a shortcut to turn your function to something which satisfies the Handler
interface.
From Simple Function to Handler
Imagine, that you have written a function to handle a request:
func hello(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
}
You could not pass it as a handler just yet. After all, it’s just a function and does not provide that ServeHTTP
method signature.
You can use HandlerFunc
to wrap this function, and have it satisfy the interface!
Here is what it looks like:
helloHandler := http.HandlerFunc(hello)
The variable helloHandler could be passed wherever an http.Handler
interface is required.
What to Use in a Function? Handler or HandlerFunc?
If you are writing a function, and have a choice whether you want to accept an argument of type http.Handler
or http.HandlerFunc
, you probably want to go with http.Handler
.
It’s a small interface, and working with minimal interfaces is where most of the magic of Go is to be found.
This way, a user could define their own struct, or use the HandlerFunc
shortcut. Both options will work if the function you are writing wants an http.Handler
type argument.
If you would ask for http.HandlerFunc
- which is not an interface and requires a specific type - the usability of your code would be arguably worse.