Golang: A simple dockerized app to demonstrate the use of Handle, Handler, HandleFunc and HandlerFunc.
Tags: go, docker
Published: 2021-09-08 11:57:01

When trying to understand how to build a web application in Go, it took me a while to understand the logic behind Handle, Handler, HandleFunc and HandlerFunc. I had a hard time grasping the logic, so I decided to write an article to make sure I understood everything correctly (which I hadn't until the middle of the writing process) and to help out others who may also be struggling.

To demonstrate the concepts of Handle, Handler, HandleFunc and HandlerFunc, we will write a very simple Go code inside of a container to serve a couple of web pages. But before checking the code, we need to have at least a general understanding of what are handlers in the context of the `net/http` package in Go.

## **What are handlers?**

On the `net/http` package, handlers are used to handle HTTP requests. This package has capabilities of initiating an HTTP server and the handlers' role is to handle the HTTP requests by receiving them and then responding back. So if the server receives a request to access the path "/products", a handler will handle that request by responding back with the code corresponding to that path. Technically speaking, a Handler is an interface that has a method called `ServeHTTP` which has two parameters: a `ResponseWriter` type (an interface) and a pointer to a `Request` type (a struct). So any object that has this `ServeHTTP` method with that signature is a handler.

## **Let's create our first page using Handle**

Now let's jump to our code! We will build a page with the path "/handlepage":

```go
package main

import (
  "fmt"
  "net/http"
)

type HandlePage struct {}

func (h HandlePage) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  w.Header().Set("Content-Type", "text/html")
  fmt.Fprint(w, "<h1>Welcome to the handle page!</h1>")
}

func main() {
  NewHandlePage := new(HandlePage)
	
  http.Handle("/handlepage", NewHandlePage)
  http.ListenAndServe(":3000", nil)
}
```
If you run the code above, and visit the page `localhost:3000/handlepage`, you'll see the message "Welcome to the handle page!". But what does this code mean? Let's take a look at the main steps.

## **Understanding the code**

First, we import the necessary packages to serve the page. Then we create a struct of type `HandlePage`. Next, we add the `ServeHTTP` method to the `HandlePage` struct (remember that any object that contains a `ServeHTTP` method with a `ResponseWriter` type and a pointer to a `Request` type as its parameters is a handler!). So by adding the `ServeHTTP` method to the `HandlePage` struct we have transformed it into a handler.

Let's look at what's inside of the `ServeHTTP` method.
```go
  w.Header().Set("Content-Type", "text/html")
  fmt.Fprint(w, "<h1>Welcome to the handle page!</h1>")
```
The goal of the code is to write a simple `html` text to the page. So we set the content type as `text/html` and then we use `fmt.Fprint` to insert the `html` text we want to write.

Next, we go to the `main` function. We start by initializing an instance of `HandlePage` and assign it to `newHandlePage`. Then we call the Handle method and pass two arguments: a string (`"/handlepage"`) and a handler (`newHandlePage`). Let's take a closer look to what this handle method does.

This is the definition we find on the official [Go documentation] (https://pkg.go.dev/net/http#Handle):
```go
func Handle(pattern string, handler Handler)
// Handle registers the handler for the given pattern in the DefaultServeMux.
```
So the `Handle` function accepts two arguments: a `String` type and a `Handler` type. But what is this `Handler` type? We've mentioned it briefly earlier, but let's take a closer look and understand how we can create a handler from a struct and then use it inside a `Handle` function. According to the [documentation] (https://pkg.go.dev/net/http#Handler), the `Handler` type is an interface that responds to an HTTP request:
```go
type Handler interface {
  ServeHTTP(ResponseWriter, *Request)
}
```
That Handler interface has the `ServeHTTP` behavior, which is the same behavior that we added to the `HandlePage` struct at the beginning of our code, so we can say that the `HandlePage` type implements the `ServeHTTP` method. When a type has all the methods defined by an interface, then we can use that type to implement that interface. What does that mean in our case? It means that we can use a `HandlePage` type as the Handler type in the second argument of the `Handle` function. So it's like we could rewrite the Handle function like this:
```go
func Handle(pattern string, handler HandlePage)
```
We can only make that replacement because our `HandlePage` type implements all the methods found on the Handler type (which is only the `ServeHTTP` method). A side note here: interfaces can be a little confusing, so if you're not familiar with it, my suggestion is that you take a look at [this article] (https://www.digitalocean.com/community/tutorials/how-to-use-interfaces-in-go) from Digital Ocean, and then at [this one] (https://www.calhoun.io/crash-course-on-go-interfaces/) from Jon Calhoun.

So just to recap, why did we add the `ServeHTTP` method to our `HandlePage` struct? So that we can use the `HandlePage` type as an implementation of the Handler interface.

What about the `Handle` function? The Handle function's job is to register the handler for the given pattern on the `DefaultServeMux` (more about this ahead). 

Finally, `ListenAndServe` is executed using port 3000. `ListenAndServe` starts an HTTP server, and when the second parameter is nil, the `DefaultServeMux` is used. `DefaultServeMux` is an instance of `ServeMux` that is used as the default multiplexer. A multiplexer's job is to redirect a request to a handler.

One interesting thing to notice is that the type of the second parameter of `ListenAndServe` is a `Handler` type. Hence, if a multiplexer (`DefaultServeMux`) is being used in the second parameter, it means it must have a `ServeHTTP` method to enable it to act as a handler. So the `DefaultServeMux` object is nothing but a handler that redirects requests made to an URL to the registered handler.

Now let's try to get the big picture of what happens when `http.Handle("/handlepage", NewHandlePage)` and `http.ListenAndServe(":3000", nil)` are executed. When `http.Handle("/handlepage", NewHandlePage)`is executed, the `NewHandlePage` handler for the `"/handlepage"` path is registered in the `DefaultServeMux`. When `http.ListenAndServe(":3000", nil)` is executed, the HTTP server is started and the `DefaultServeMux` can then redirect requests according to what was registered on it (so far we only registered the relationship between the `"/handlepage"` path and the `NewHandlePage` handler). When the `"/handlepage"` path is visited, `DefaultServeMux` redirects the request to the `NewHandlePage` handler and the `ServeHTTP` method is called, executing the code inside of it. So in our case, when we visit `http://localhost:3000/handlepage`, the code inside the `ServeHTTP` method,
```go
w.Header().Set("Content-Type", "text/html")
fmt.Fprint(w, "<h1>Welcome to the handle page!</h1>")
```
is executed and we see the "Welcome to the handle page!" written on the page.

Ok, so now we have a general understanding of what handle and handlers do and how they relate to each other: the first is a function that uses the second, an interface (or an object that implements that interface), as one of its parameters. So since a `Handle` uses a `Handler` as one of its parameters, can we infer that `HandleFunc` uses a `HandlerFunc` as one of its parameters too? Well, not necessarily. So what is the difference between a `HandleFunc` and a `Handle` and between a `Handler` and a `HandlerFunc`?

Let's continue with our example to have a better understanding and make a brief recap on what we've done so far to create our single page on `"/handlepage"` using only Handle and Handler:
1- Created a `HandlePage` struct;
2- Added the `ServeHTTP` method to the `HandlePage` struct;
3- Created an instance of `HandlePage` and name it `NewHandlePage`;
4- Executed `http.Handle` having `NewHandlePage` as its handler.

Now let's assume we want to create several pages. If we follow the logic above, we would need to create a struct for every page and then add the `ServeHTTP` method to each. `HandleFunc` and `HandlerFunc` can help us simplify this flow. But how? Let's see!

## **The second page: using HandleFunc**

We will now create a different page, with a path `"/handlefuncpage"`. Let's add to the previous code all the steps necessary to create and serve this new page, but now using `HandleFunc` instead of `Handle`. Here's how our new code looks like:

```go
package main

import (
  "fmt"
  "net/http"
)

type HandlePage struct {}

func (h HandlePage) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  w.Header().Set("Content-Type", "text/html")
  fmt.Fprint(w, "<h1>Welcome to the handle page!</h1>")
}

func HandleFuncPage(w http.ResponseWriter, r *http.Request) {
  w.Header().Set("Content-Type", "text/html")
  fmt.Fprint(w, "<h1>Welcome to the handlefunc page!</h1>")
}

func main() {
  NewHandlePage := new(HandlePage)
	
  http.Handle("/handlepage", NewHandlePage)
  http.HandleFunc("/handlefuncpage", HandleFuncPage)
  http.ListenAndServe(":3000", nil)
}
```

So which steps did we have to take to create the new page on `"/handlefuncpage"` path?
1- Created a `HandleFuncPage` function;
2- Executed `http.HandleFunc` having the `HandleFuncPage` function as its second parameter.

When comparing the steps made to create the page on `"/handlepage"` and the ones made to create the new page on `"/handlefuncpage"`, we will see that we can replace the first's three steps by the second's first step: instead of i) creating a struct, ii) adding the `ServeHTTP` method to it and iii) creating an instance of the struct, all we had to do was to create a function having a `ResponseWriter` type and a pointer of an `Request` type as its parameters. But how is this simplification possible? Let's compare `HandleFunc` to `Handle` and understand the differences.

```go
func Handle(pattern string, handler Handler)
func HandleFunc(pattern string, handler func(ResponseWriter, *Request))
```

When comparing `Handle` and `HandleFunc`, we see that the second parameter, the handler, is different: whereas in `Handle` it is a `Handler` type, in `HandleFunc` it is a function with a `ResponseWriter` type and a pointer of `Request` type as parameters (yes, the same signature of the `ServeHTTP` method). So this means that to use `HandleFunc`, we need to have a function with the proper parameters to make it work like a handler. Once this is done, `HandleFunc`, when executed, will convert this function into a handler and register it on the `DefaultServeMux`.

Right, but where does `HandlerFunc` enter after all? It's nowhere to be seen in our code! To unfold this mystery, we first need to understand what a `HandlerFunc` is. 

## **What is `HandlerFunc` and where is it?**

A `HandlerFunc` is a function type that can convert any function with the right signature into a handler. But what is the right signature the function must have? Yes, the same signature of the `ServeHTTP` method: a `ResponseWriter` type and a pointer to a `Request` type. So when we have a function with that signature, we can use `HandlerFunc` to convert this function into a handler, allowing us to use it as the second parameter of a Handle function, for example. 

One thing to notice is that `HandlerFunc` converts the function to a `HandlerFunc` type, and not a `Handler` type. So how can we use this `HandlerFunc` type as a handler? Because a `HandlerFunc` type implements the `ServeHTTP` method, the same method that the `Handler` type implements. Remember the interface logic we mentioned earlier: when a type has all the methods defined by an interface, then we can use that type to implement that interface. 

Let's check the `ServeHTTP` method added to a `HandlerFunc` type and see if there's anything interesting:

```go
// The HandlerFunc type is an adapter to allow the use of
// ordinary functions as HTTP handlers. If f is a function
// with the appropriate signature, HandlerFunc(f) is a
// Handler that calls f.
type HandlerFunc func(ResponseWriter, *Request)

// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
  f(w, r)

```

When we convert a function to a handler using `HandlerFunc`, a `ServeHTTP` method is added to it. Calling `ServeHTTP` on this new handler will simply call the underlying function (`f(w, r)`). Think of when we added the `ServeHTTP` method to the `HandlePage` struct: calling `ServeHTTP` on this struct simply executes the code we wrote inside of it. The `ServeHTTP` method inside of a `HandlerFunc` type was built to have the same effect: execute the underlying function and hence the code inside of it.

Being able to convert any function with the appropriate signature into a handler is quite handy :smiley:, but going back to our mystery, we don't see this `HandlerFunc` being used anywhere. When we call `HandleFunc` in our code using our `HandleFuncPage` function as its second parameter, everything works as expected, as if the function is already a handler. How can this be?

To understand what is happening behind the hood, we must check the source code of `HandleFunc`:

```go
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
  if handler == nil {
    panic("http: nil handler")
  }
  mux.Handle(pattern, HandlerFunc(handler))
}


func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
  DefaultServeMux.HandleFunc(pattern, handler)
}
```
Ah! Now we can see `HandlerFunc` in action! Notice in the last line of the first block that `HandlerFunc` is being used to convert the function called handler into an actual `HandlerFunc` type (`HandlerFunc(handler)`). It is very important to understand that whenever you see something like `var nf http.Handler = http.HandlerFunc(notFound)`, it means that you are converting a function into a handler type (in this case, we are converting the function `notFound` into a handler). Some people who are not familiar with how `HandlerFunc` works might think that it is a function call having `notFound` as an argument and that it might return a different thing.

Going back to our code, that's why when we called `http.HandleFunc("/handlefuncpage", HandleFuncPage)` everything worked: `Handlefunc` converted the `HandleFuncPage` function into a handler under the hood.

Right, so we now understand what a `HandlerFunc` does and how it is used by `HandleFunc` to convert functions into handlers. In our case, we didn't have to use `HandlerFunc` explicitly, but there might be cases where we would want to convert our functions into handlers and then use them elsewhere. For example, if for some reason we wanted to keep using `Handle` instead of `HandleFunc`, we could have converted our function `HandleFuncPage` using `HandlerFunc` and then used `Handler` to register it on `DefaultServeMux`, like this:
```go
//Convert HandleFuncPage function into a handler:
hfp := http.HandlerFunc(HandleFuncPage)
//Use the converted function as a handler using Handle:
http.handle("/handlefuncpage", hfp)
```
Remember that the `Handle` function doesn't convert functions to handlers, so that's why we need to convert the function to a handler and then pass it inside `Handle`. In fact, `HandleFunc` was a shortcut created to avoid having to explicitly convert functions into handlers.

## **The end**

And that's it! I hope you enjoyed this article and that your understanding of all those handy stuff is now a little bit better. 

You can find the code [here](https://github.com/isabelatravaglia/go-handlers-article). You can open it in a devcontainer if you are using VSCode.

Thanks!