As the title states, did you switch to Go/Golang for developing REST api’s or other kinds of web services? What has been your experience? Would you use Go again in the future? Would you rather use something else?
Yes, in 2017 and 3 companies later I've never looked back. Current application is an event-sourced system that includes a REST API, asynchronous event processing over SSE, and a scheduled job runner.
It's been great. We don't use any frameworks, just the http package. It's blazing fast and highly reliable (low bug occurrence and easy refactors due to the safety provided by strong typing).
If you're open to it, I'm curious about a few things:
1. How do you handle DB interactions? A data mapper/repository pattern?
2. Do you have a service layer to coordinate between the different "inputs" (the REST API, event processing, and scheduled jobs)
3. Is this REST API used by a web front end or other services? Interested in how people handle token auth and/or using session tokens.
I've been reading about architecture patterns more and I've realized which patterns I've used without knowing it, so now I'm interested in how others handle similar situations in different languages and ecosystems.
What were you using before Go? I notice in the relies that a lot of people are coming from Python. Did you consider using Java? And if so what made you use Go in the end?
I've used many languages in my career, including Java, Scala, Ruby, and Node. I didn't really consider Java, for a couple of reasons.
- I didn't love the Java tooling at the time. Maven for example.
- I don't love OOP. Go has just enough OOP patterns for me.
I tried Go as an experiment, but didn't know it would become my go-to language. What I found was super fast build times (big win), built in testing, and a simple language that almost anyone can understand (versus the relative sophistication of something like Scala).
I went from Python to Go to Rust. Go plays up this fantasy of types helping you catch bugs, buts it’s really C with lipstick. There’s no enums, no exhaustive matching of any kinds, there’s null to worry about everywhere, and every utility function has to be painfully written out for each type (maybe that’s starting to change now with Go having basic support for generics).
I went from Python to Rust to Go. Python I won’t spend long on, it’s problems are well documented. Rust, which I use wherever possible, just is not the right language for apis for me. Adding dependency injection through Boxed traits feels like you’re taking a performance hit just so you can test code. Also, I spent a couple hours on trying to get async traits to work with a mocking lib and gave up. Switched to Golang. It’s not without issues but for now I’m productive.
I switched from Python to Go for API development and never looked back. Performance is great, deployment is a breeze and the compiler and type system are good enough that my code normally works on the first try. I've also been building AWS Lambda backends and Go is great in that role as well. Workloads complete much more quickly than equivalent Python code and use a fraction of the memory.
It's no BS, go is much more performant. There are a lot of benchmarks out there. In the context of Lambda, it probably helps that I'm just shipping a compiled Go binary rather than a Python environment + dependencies. Regardless, there are Lambda workloads that are trivial with Go that are pretty much impossible with Python because of run time limits etc.
First of, just like the term "hacker" became popularized by the media and turned into the meaning of someone who cracks computers and software, so has HTTP based APIs been popularized and turned into REST applications, but this is wrong. A HTTP based API cannot, by its very nature, ever be REST.
Now that's out of the way, yes. We use Go for both API and web development, actually full stack WITHOUT any JavaScript. We have written a custom error handler that deals with runtime HTML template errors, if any, which improves the otherwise tedious work when a template makes the web service crash.
Go is superb at HTTP and all web related. We still have some PHP development, but would very much like to do Go all the way, we just haven't gotten there yet.
Last, but not least, we do not use any frameworks or libraries, only the Go standard library and we love it. No matter were we put it, it just always works and is very performant.
Or one could include a link to an Open API spec for the API in the response of every request that details all endpoints available and their parameters/bodies.
No, that would not make it REST. I suspect you didn't read the article thoroughly?
If your application needs documentation, i.e. a spec or similar, also referred to by some as a "profile", in order for the client to use your resources beyond the initial root URI, then that is not REST!
An API, no matter how you twist or turn it, can never be REST. REST are truly only for manual human consumption, not machines. That is why it is so weird everyone is calling their APIs for REST.
If an API response included all the possible actions and information that one takes as a follow up to a previous call, how is that any different from providing the equivalent forms and links to additional information on a web page rendered by a browser?
It certainly seems possible to pigeonhole an API into a RESTful architecture but I understand why based on the article, APIs aren't often considered RESTful.
But it seems they can be. I see this as a proof by contradiction.
I, today, can navigate directly to posts by a friend of mine on a social media site. Auto logged in, not having to enter any form data etc. That's my starting point both in a browser and via API.
I'd see their post. Alongside that post I'd see actions I can take: clicking on other friends' profiles, liking the post, commenting on the post, removing the friend etc.
In this way, the response to my request includes all the possible actions I can then take and what data I need to provide to take it (in the example of the comment route).
* No consulting of external documentation is needed, all the information is right there. *
I can explore another user's profile (people with user ids of 13, 14, and 15), I can like and unlike this post with the `/like/` and `/unlike` routes, I can remove this person from my friends list etc.
Including such information makes this response no different than what I can do via browsing the page - all my interactions with the API are directly driven by their responses - not by consuming outside documentation.
If all possible actions and their routes were included on route supported by my API, why would this not be RESTful?
At the end of the day - this to me is a distinction without a difference. Whether this documentation is defined as part of the response or stored in an OpenAPI spec, the end result is the same - I can easily wire things up together to accomplish my goals.
This is where SDKs become more useful.
SDKs are fully documented, require no external information for them to be used, contain everything possible that can be done as methods etc.
If I get a `User` class back from an SDK - I can then invoke all the methods on that user like - getFriends, getPostById, etc etc.
If I call a `getFriendById(12)` method I'd expect a `Friend` instance rather than a more generic `User` instance which should have a `removeFriend` method but no `addFriend` method. That appears equally as RESTful as a website with actions that can be taken.
You're missing the point. If you provide an API like in the example you give, put it out on the net at some domain, then in order for it to be REST, I MYST be able to access that domain, without any prior knowledge whatsoever, and make a request.
When I do that in the case you provide, I would not know anything about how to use those resources. Without any prior knowledge, I don't know what "users" are, or what a "like" is or an "unlike". In order for me to use this resource, I need documentation. Even if you provide the documentation in the response to the request, and I have to read that first, then it is NOT REST.
By the very nature of an API, it can never be REST.
Okay, I understand the distinction but as I said, it seems to be a distinction without a difference.
The idea of REST has evolved beyond the initial definition to include a broader and far more impactful meaning. The abstraction of UI over data. The important piece is the data.
I could make an entire website, entry point and all that only returned json and included the links for actions users could take and other pages they could visit. Whether I use a browser to see that or my terminal with a cURL makes no difference.
Can I ask about the choice to not use any libraries? As in your go.mod file is empty? I understand the desire to keep dependencies to a minimum but surely there are use cases where it is better to import existing code rather than writing something from scratch no?
We basically only use the Go standard library. So far we have found no use cases where that didn't cover us well enough.
This also removes any problems with third party dependencies that suddenly gets abandoned yet still have serious issues, supply chain attack problems, etc.
We have also found that most third party libraries tries to be (more or less) general purpose, so they often contain lots of stuff we would never need, so we prefer to e.g. write our own specific code.
The way we work require a little extra effort because we write the things we need our selves, but of course we reuse our HTTP handler code, our custom runtime error handler code, etc., from project to project, but in general the benefits far outweigh the cost in our experience. The fewer dependencies, the fewer problems - and Go shines in this because of how much is covered in the standard library.
Can you elaborate on why HTTP APIs cannot be REST APIs? I know a lot of http services are misclassified as REST, but why can they by definition not be?
The author got Roy T. Fielding, one of the principle authors of the HTTP specification and the originator of the Representational State Transfer (REST), to comment on this issue by email (was since removed when the author changed his blog).
I made a few APIs on Golang and it was fine. It was easy and it performed well in production for many years.
Today, I would go with Rust instead because of personal preferences. But if my code base has to be shared with not very experienced developers, perhaps Golang again.
Because of the stable nature of the base language and library, and the way libraries are imported, with multiple pinned versions allowed and without import loops, it gives better longevity to "set and forget" type back-end services.
I rarely have a problem when coming back to work on an old project, it still compiles and even updating dependencies is usually fine.
This helps with the problem of back-end services becoming "forgotten children" that don't receive attention for extended periods.
When some of the teams I've worked with switched from PHP / Laravel to go the most common complaint was that their code must be broken because it was just too fast.
Yes - for cloud functions. Even reasonably simple python APIs can exceed the 128mb lowest mem spec while go equivalent gets you an extra 60 ish meg breathing room
My team and I have built many dozen services using Go and Fiber (fiber.io) and have been insanely pleased with the experience and the performance of the code. We have quickly onboarded new devs and got them productive very quickly thanks to the relative simplicity of the language, amazing documentation and strong start of tools. We are writing most of our components, APIs and tools in Go. Go for it!
Yes, go is still my go to technology for API work. I usually go about it like this: write an OpenAPI spec, generate clients and servers, implement individual operations. I like how lightweight a go implementation is and how easy, no-bs it is to setup a new module. I like go for apis.
Did you ever build HTTP based APIs in Java (or C#), what makes you prefer Go?
I have been using Java for a long time but will soon be using Go because of a job change and I am trying to get a better sense of the trade-offs and advantages.
Yes there is something about it that is actually fun... there's a productivity sweet spot, it makes sense and you know it's probably going to work first time (at least compared to many other languages) - so you spend more time expressing ideas and solving problems.
Look into the embedded filesystem for storing static stats and metric pages, it's nice to have that packaged up in the same single binary and goes a long way in making small webserver utilities more usable.
It's been great. We don't use any frameworks, just the http package. It's blazing fast and highly reliable (low bug occurrence and easy refactors due to the safety provided by strong typing).