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.

Newsletter

It's the really early of this site! There is no automated newsletter signup yet. But if you want to stay posted already (thanks!), send a mail to mail@vsupalov.com. Just say hi and that you'd like to get notified about new Gophed Dojo articles. There's also an RSS link in the footer if you prefer!

gopherdojo.com

© 2024 gopherdojo.com. All rights reserved.