Skip to content

Instantly share code, notes, and snippets.

@drgomesp
Last active January 8, 2021 16:39
Show Gist options
  • Save drgomesp/a262656dcece2559ac24d5daec72537a to your computer and use it in GitHub Desktop.
Save drgomesp/a262656dcece2559ac24d5daec72537a to your computer and use it in GitHub Desktop.
beyond-the-basics-of-go-http-handlers.md

Beyond the Basics of Go - HTTP Handlers

http.Handler and http.HandlerFunc

The Go standard library defines two main components for dealing with incoming HTTP requests: the http.Handler type and the http.HandlerFunc type. While http.Handler is an actual interface,

type Handler interface {
	ServeHTTP(ResponseWriter, *Request)
}

http.HandlerFunc, on the other hand, is just a type definition,

type HandlerFunc func(ResponseWriter, *Request)

which is even more flexible and allows the usage of ordinary functions as HTTP handlers, as long as they have that signature.

The way you implement your handler is really dependent on what you want to achieve and also the limitations of each approach.

Using the http.Handler interface requires you to define a type which implements that interface in order for it to be treated as a Handler. Here's an example:

type foo struct {}

func (h *foo) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    w.WriteHeader(http.StatusOK)
}

Using the http.HandlerFunc type is even easier, and requires you to simply have any function which respects the signature func(http.ResponseWriter, *http.Request) passed to whoever is using the handlers. Here's an example, where Foo is a valid HTTP handler:

func Foo(w http.ResponseWriter, req *http.Request) {}

In any case , once you have a valid handler, you can serve HTTP requests by writing very simple code (specifically, making use of the http.Handle, http.HandleFunc and/or the http.ListenAndServe functions), which might look like this:

http.Handle("/foo", foo) // Assuming you implemented the http.Handler interface
http.HandleFunc("/foo", Foo) // Assuming you defined Foo as an http.HandlerFunc

log.Fatal(http.ListenAndServe(":8080", nil))

Here, nil is being passed to http.ListenAndServe so that internally it will use its default implementation defined in net/http. The default implementation is a package instance variable of a another important component: the http.ServeMux.

The http.ServeMux struct

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment