From Python to Go or Rust?
Nowadays there are plenty of options for building backend systems, both in terms of programming languages as well as frameworks, each of them having their own strengths and weaknesses.
In Octobot we’ve been working with Python/Django for quite a while and are really happy with it. We are able to quickly develop scalable systems thanks to the high productivity provided by Python and all the amazing features included in Django.
However, there are cases when the performance comes in as a major requirement and in this type of situation Python just isn’t the best option. For this reason, we recently decided to incorporate a new language to our technology toolset.
In this context we ended up trying to decide between two very compelling options… you guessed it, Go and Rust.
About Go and Rust
Both Go and Rust are modern languages (from 2009 and 2010 respectively) that fit our desired description: a high performance language and platform that is reliable and brings modern features that boosts productivity.
Other similarities include being compiled and statically typed languages with great support for concurrency. On the other hand, some of their key differences are that Go focuses on simplicity and makes use of a garbage collector, while Rust focuses on efficiency and memory safety.
Despite these differences, they often end up in discussions as of which one is better or which one you should use, and the reality is that both have proven to be great options for most given problems.
So when we approached this question we did so with a rather specific goal: evaluate how it feels to face both of these languages for someone of our background; that is, someone who has mainly been working with a scripted, dynamically typed language like Python and a rich, relatively opinionated framework like Django. By doing this we expected to get a more realistic idea of which one would be better suited for our team.
In order to make this comparison, I settled on the task of learning the basics of both languages by giving each a similar amount of time and then implementing a simple REST API that interacts with an SQL database. This is one of the most common scenarios we face on most projects, so it should give me a relatively realistic idea of how it would be like working with each language.
The decision of giving them a similar amount of time to learn may not be completely fair since Rust is known to be more complex than Go, but since this is precisely one of our concerns I thought it was appropriate to keep it that way.
The following points summarize some of the takeaways from this brief experience and cover the aspects I consider relevant when picking one over the other. Keep in mind that many of these things are subjective and based on my own experience.
When it comes to learning the basics, both languages seem to be well covered. The official documentation for any of them is really great and I didn’t have any problem looking for non-official resources either.
On the Go side, “A Tour of Go” is a well-guided introduction to the language, really easy to read and full of interactive examples that allow you to start trying things right away on the browser.
The Rust “Book” on the other hand, while still great and nicely organized, is a much more detailed introduction to the language, and the many concepts present in Rust. Right from the start, it manages to feel way more complex than Go, particularly when it comes to some of the memory-related restrictions, but even though it may be a bit time consuming I wouldn’t recommend starting coding before reading at least a considerable portion of this book.
Moving on to the installation and building a simple “Hello World” project, it was pretty straight forward for both languages. Even adding external libraries was extremely simple thanks to the dependency management systems built in both languages.
For the text editor, I used Visual Studio Code and ended up having some issues with the Rust extension which for some reason just didn’t work. I’m not sure if it was some specific problem on my machine but I thought it was worth mentioning.
The Go extension on contrary worked great and ended up adding a lot to the coding experience.
Lowering compilation time was one of the motivations behind the development of Go, so it isn’t a surprise that Go code compiles faster than Rust. This may not be a problem nor a feature for many people but it’s another thing to keep in mind.
In our small examples, I could already see a difference of a few seconds when compiling each language, near 1 second on Go vs 7 seconds on Rust (dev build). I’m not sure how big this difference would be on larger projects but it might be something to look up if compilation times matter to you.
Here Go really does shine. It comes with a wide variety of built-in packages, including almost everything I needed for this test project, like the webserver, JSON serialization, and database management (this one at least to some extent).
These packages offer some production-ready functionality and come with great documentation, easily accessible through the Go official web page. They also add up to the simplicity of the language in a way by avoiding the need for many external dependencies.
For Rust, I needed external libraries for basically every step of the development process. This added some extra complexity and less clear documentation along the way, which ended up being one of the most time-consuming aspects of my Rust implementation, figuring out which libraries I should use and how to make them work the way I wanted.
The coding experience is probably the most relevant, yet most subjective aspect of this comparison, how easy was it to get things done in each of these languages?. It may be clear at this point that when it comes to productivity, Go is probably the language to go with (pun intended).
The simplicity and smaller number of features of the language definitely make it easier to start writing code right away, while as mentioned before, the large amount of new and relatively complex concepts in Rust do make it harder to learn, and I feel it may take weeks before being comfortable with it. Even basic things like splitting code into different files in Rust required me to read multiple pages of documentation while being almost trivial in Go.
As mentioned earlier, the need for external dependencies was also a bit of a problem when working on the Rust implementation. The documentation of the frameworks and libraries I ended up using (which were popular ones by the way) was often confusing and I would quickly feel lost when deviating even a little from the given examples.
With Go on the other hand I felt much more comfortable when trying different things, faced fewer compilation errors, and navigating through the package’s documentation was also way more intuitive.
Speaking of compilation errors… not only I had more of them while working with Rust, but I also noticed it was easier to run into harder to understand ones on Rust that it was on Go. However, despite being frustrating it’s fair to say that this is a problem that will mostly affect beginners, and the fact that the compiler in Rust is so strict is also considered an advantage since once it compiles it is less likely that your code will behave in unexpected ways.
Finally, another thing I liked about Go was it’s official (and well-accepted) set of conventions on how to write clear code (here), that alongside the already mentioned simplicity and rich standard library helps to make Go an easy to read and easy to maintain language overall.
After giving each of this two languages a try, if I had to pick one over the other in order to fill the gap mentioned at the beginning of this post it would certainly be Go, but just to be clear, this decision is heavily based on our specific goals and context, and I would definitely recommend any of the two for anyone willing to learn a new language.
Even though my personal experience was more pleasant while working with Go I could also see why Rust is loved amongst its users, it has a bunch of interesting features and concepts that make it a unique language, capable of basically anything once you mastered it.
That being said, Go’s balance between speed and simplicity makes it an excellent choice for building backends and microservices where you need high performance while still keeping your induction and development time reasonably low.
Once again, this was based on my personal experience and research but I still hope it can be helpful for anyone facing a similar situation.