I built many REST API in Go, and even though it is quite simple and fun, at some point it is repetitive and error prone. Generics gave me the solution to reduce all that pain. But it gave me more, and the capacity of creating some full REST API with HATEOAS within minutes, while separating data storage concern in other part of the application.
What it does
RIP lets you have REST, in Peace.
You implement some data/business resource access interface, and you can plug it directly in the standard
Now, your resource is automatically served with standard REST HTTP verbs, in the format you want (
text/xml? your own presentation format adapted from the client (mobile, web)?)
How we built it
The idea was to plug it in the standard library as much as possible. As it is related to web, respecting
net/http function signature was very important as it would enable people creating REST services with fewer dependencies.
Go parametrized types enabled us to create generic HTTP handlers that would do the same process for each type.
Challenges we ran into
Understanding what I can accomplish with Go parametrized types and what I can't.
- Mixing interface and parametrized types has limits, and the compiler can't figure out some cases.
- Keeping interfacing with
net/http.HandleFuncwas tricky if I needed knowledge of the path that was served. My API reflects that: it returns
- Having a nice error API
Accomplishments that we're proud of
Being able to create this package is an accomplishment in itself, as I was one of the few gophers wanting generics, and had a use case in mind that wasn't a specialized container package. And now that it's created, I can start thinking of using it for real projects.
What we learned
- The limits of Go parametrized types implementation
- Good API design is hard.
What's next for RIP
- add HATEOAS functionalities, hypermedia discoverability (the API root should display the resources availables to interact with, etc)
- improve error API
- let you drill down inside of resources fields in a RESTful way:
/users/:id/namewill let you GET/POST/PUT into that resource field, for example