Go is regularly criticized for odd decisions and idiosyncrasies, while Rust is celebrated as an almost perfectly designed alternative that solves Go's problems. But in fact, Go and Rust are far from interchangeable.
Posted on September 28, 2021
When reading I want off Mr. Golang's Wild Ride and the heated discussions around it, I came across statements like "Rust is what Go should have been" more than once. The consensus in these discussions, obviously driven by that article, was that Go had too many questionable idiosyncrasies and Rust, on the other hand, was a well-designed alternative to Go.
From my point of view, the article as well as the discussions revealed a substantial misunderstanding about the two languages, the problems they solve and the software development paradigms they aim at.
The article in question mainly criticizes that Go's simplicity was a lie: APIs in the standard library were hiding complexity from the user
without actually solving it, which produced strictly incorrect results in edge cases. Go's
filepath.Ext function is used as an example: It
produces inaccurate results in some circumstances. As a counterexample, the article refers to Rust's
std::path::extension function that produced
entirely correct results.
This resentment about Go's inaccuracy in edge cases seems understandable. We've all learned that in programming, there only are correct and incorrect results, with nothing in between. Therefore, since Rust delivers correct results, it obviously has to be the better language. But are things really that simple? And wouldn't Google be able to hire someone good enough to fix this?
Go and Rust probably are compared so frequently because both were advertised as systems programming languages, plus they were released shortly after each other. But once you internalize where they came from and what purposes they have been designed for, it quickly stands out that they are two entirely different languages.
Go is a Google project mainly designed for internal backend- and networking services. Those services run in a predictable, homogenous, Unix-only infrastructure. Google is in full control of their infrastructure, and potential performance bottlenecks may be solved by just throwing more servers at the problem.
On the other hand, Rust was started by Mozilla under very different circumstances. Projects like Firefox and Servo are very long-lived software products that have to run on all kinds of systems. They have to work in inhomogenous, unknown and possibly hostile environments. Consequently, producing the exact same results on each and every system is crucial for those applications.
Google and many other companies that maintain a similar kind of infrastructure typically have to deal with the following challenges - and while I don't have deep insights into Google, some of them probably are amplified by its sheer scale:
Google needed a language that is exactly tailored to these challenges, and it inevitably would be designed differently from a language that serves Mozilla's needs.
Go and Rust not only have different language designs, they also embrace a contrary kind of software development. Rust focuses on high efficiency and finding the most beautiful implementation for a problem. To achieve this, it accepts a much steeper learning curve compared to other languages.
In contrast - and this is the reality in large parts of the industry - Google and many other companies don't want their developers to spend 3 months learning a new language before they can be productive. Therefore, Go has been deliberately designed as a quick-to-learn and pragmatic language. It doesn't have to be the most efficient or most beautiful solution. It even doesn't have to work on systems the company isn't using anyway. It just has to work good enough.
Why? Because running dynamic infrastructures requires a high degree of automation, standardization, monitoring, observability, resilience, scalability and security. It may sound odd for developers that don't work in such an environment, but in daily business, the focus often is on these high-level demands rather than on the code itself.
Even though Go and Rust seem to offer similar benefits for similar scenarios at first glance, they're rather specialized tools for different problems. Just as with most other tools, one isn't just "better" than the other. Neither Google nor Mozilla took a biased approach when they were looking for a new language that fits their needs. They simply strived for the solution that would work best for them - and so should you.