Let's understand Go Handle(r) family - last thing you need
%20family%20(1).png&w=1200&q=75)
Go Handler Family Diagram
When you begin writing HTTP servers in Go, the words Handler, HandlerFunc, Handle, and HandleFunc look confusing. They sound similar, but each plays a clear role. Once you see how they connect, everything becomes simple.
Go's HTTP system starts with the Handler interface. It has just one method:
Any type that has this method becomes a Handler. For example, a struct can turn into a Handler like this:
Now this struct can be registered in the router.
The next piece is HandlerFunc. This is not an interface. It is a function type:
Go attaches a method to this function type:
This means any ordinary function with that signature automatically behaves like a Handler. Example:
Because this function matches HandlerFunc, you can register it like this:
Or using the shorter helper:
This is where newcomers get confused. The difference is simple:
Handle expects something that already implements the Handler interface.
HandleFunc expects a plain function, and Go converts it into a HandlerFunc automatically, which already has ServeHTTP.
So if you write a struct with ServeHTTP, use Handle:
If you write a simple function, use HandleFunc:
Both eventually produce a Handler. The only difference is whether Go wraps it for you or you pass a Handler directly.
This entire design keeps Go's HTTP package clean and flexible. You can use functions, closures, or full struct-based handlers. Everything works because HandlerFunc turns a normal function into a real Handler by giving it the ServeHTTP method.
Once you understand that, the whole Handler family feels natural: Handler is the interface, HandlerFunc is a function type with ServeHTTP, and Handle/HandleFunc simply register your routes.