RESTful routing in Go

05 May 2015

A few days ago, I wrote about wrapping Go HTTP handlers so that they can return an abstract Response object rather than dealing with http.ResponseWriter. Today I want to focus on the other end of the request: routing.

What I'm doing here should work with any of the many third party HTTP routers (aka multiplexers) that support URL parameters. I'll be using my own, but adapting it to something else should only require a few small changes.

An anti-pattern that I've seen from the Go community is defining specific routes as opposed to using general patterns. I'm by no means dogmatic when it comes to URL patterns, but I do think having consistent and human-readable URLs is beneficial.

# bad
GET /users
GET /users/:id
# good
GET /:resource
GET /:resource/:id

Ultimately, goal is to end up with a map of resources + action names (users show, users favorite list, sessions delete) to handler functions. As a first step, we can manually create this mapping:

It's small improvement that further enforces consistent naming and reduces some of the magic strings. Unfortunately, in Go, it isn't possible to scan a package for functions of a given signature. If it was, we'd be able to automatically detect and register actions.

Finally, this approach doesn't exclude the possibility of having one-off routes for cases that don't fit the general patterns.