/
Write
Start a team blog
NEW ✨
Start a team blog, invite your team, and start publishing.

Generics based http handlers in go - Part 1: Why

Jimmie Butler's photo
Jimmie Butler
·Mar 12, 2022·

1 min read

Handlers in go have suffered from a large amount of boilerplate. Often something like this is written for each handler.

func(w http.ResponseWriter, r *http.Request) {
  userID := middleware.UserIDFromContext(r.Context())

  data := Widget{}
  err := DecodeAndValidate(r, &data)
  if err != nil {
      http.Error(w, err.Error(), http.StatusBadRequest)
      return
  }

  // Do something with the data
}

DecodeAndValidate must come after we declare data := Widget{} to get us a type safe instance of widget. This makes it difficult to put this logic that is shared across most handlers in a common middleware or similar component.

Generics can help here. We can write our handlers like this, with our common unmarshal/validate code outside our main handler. This gives us a much cleaner, and in my opinion potentially safer handler since it's less code to introduce bugs and maintain.

func(w http.ResponseWriter, data *Widget) {
    // Do our widget work, confident things have already been validated and unmarshaled
}