Earlier this week, a 2-year old post titled I want off Mr. Golang’s wild ride by @fasterthanlime made the news rounds again. This post raises a bunch of concerns on the Go language and is posted from the perspective of someone who prefers Rust. And, just yesterday, I noticed a comment on Twitter by @FiloSottile that, paraphrased, reads “Why is there so much hatred towards Go, especially from Rust developers?”.

I wish I could answer this question with a “no, there isn’t”, but that would be a lie: in any large community, there will certainly be hateful people/opinions. If you have encountered such flamebait, I’m sorry, and I’m not here to defend it. What I’m here to do is look at the possible truth behind the claim that Rust developers dislike Go, and I wanted to elaborate on this based on my personal experience.

A blog on operating systems, programming languages, testing, build systems, my own software projects and even personal productivity. Specifics include FreeBSD, Linux, Rust, Bazel and EndBASIC.

0 subscribers

Follow @jmmv on Mastodon Follow @jmmv on Twitter RSS feed

I have taught myself both Go (in 2016) and Rust (in 2018). I have written the exact same project—sandboxfs, a FUSE file system—in both languages, which allowed me to experience pretty closely how these two languages compare for high-performance systems-level software development. I have written other code in both as well, using Go when I was at Google and Rust for a side project.

And, you know, I enjoy writing code in both languages. They are fun; they make me productive; they are better than the alternatives. You can read my review of Go in 2016; my review of Rust in 2018; and my comparison of both languages in 2018. So, I do have some “comparable” experience with these two languages and, based on this experience, I think I understand where some of this “Go hatred” comes from. And I would say that this hatred comes from sadness.

From the very beginning, Go has been touted as this systems-level language that can replace C and C++ in large-scale projects. A super-simple systems language that is safer than C and almost as fast as C. And, yes, Go is indeed a simple language: you can learn Go in a day (yes, really) if you are already familiar with a C-style language, and you can start writing code right away, which is really empowering. The problem is that, like with any other language, mastering Go idioms and best practices will take much longer though—so don’t go write your next startup’s foundations in Go just with a weekend’s worth of experience; it feels like you can do so, but it would be an uninformed choice.

Other than being simple, Go is also extremely nice to interact with: enforced code formatting, simple build tools, a builtin profiler, a comprehensive core library, super-fast build times… These are all qualities of the Go ecosystem that increase individual productivity very quickly and with little effort. You can imagine that these are very appealing when working on a greenfield project, especially with a team, because you can start shipping soon.

OK, so Go is great. Then, why the hatred sadness towards it? And why does Rust have anything to do with it?

To answer this, we have to start from the assumption that Go and Rust are competing for the same systems development space; that is, finding an alternative to C and C++. This assumption may or may not be valid, but I believe that lots of people come to these languages with this preconception in mind (myself included). As a result, it’s not a matter of choosing Rust or Go for a specific task: it’s a polarizing topic.

Once you start with this assumption, if you learn Rust after Go, you realize how much better (in safety, performance and agility terms) systems programming could be if we used Rust throughout. But because Go is so widespread and gives the (false) impression of being much easier to master, Rust is likely to lose the battle. And, unfortunately, most technical decisions at the beginning of a project—which language, which database, which cloud provider, etc.—are made based on gut feelings and superficial information. By the time problems become apparent, it’s a gargantuan task to change those choices.

And here is where the sadness comes in. Once you learn Rust and experience what it brings to the table, you start finding gaps that Go doesn’t cover, which means that if we double down on Go, we perpetuate these problems. Null pointers are there. Data races are there (because, even if you have channels, you also have mutexes and you ought to use them for performance reasons). Garbage collection is there. Duck typing and the widespread presence of interface{} make refactoring difficult. And my pet peeve: annotations to express safety constraints on the code are notably not there, resulting in lots of comments and dumbed-down runtime error checking that shouldn’t be necessary.

Note that I am intentionally not mentioning Go modules or generics here. I know these features have been controversial for a really long time and, fortunately, they do exist now in Go after years of debate. I’m glad that they do, but the core issues with Go don’t stem from the lack of features. They stem from the foundations of the language.

I get why Go is so appealing. And I also understand that Rust can be very off-putting at first. But I don’t like to think of a future world where systems are all written in Go. Such a world would definitely be a better than the current world dominated by C and C++ memory leaks and buffer overruns, but we would still suffer from many issues that simply wouldn’t exist if the same software had been written in Rust. And that is what I think bothers people. Well, at least it bothers me a little bit.

Just as an example to illustrate why these design choices get in the way, I want to go back to my sandboxfs experience. When working on the Rust rewrite, I used the Go implementation as a reference and tried to translate the code while keeping a similar design. During the process, I remember spotting many subtle bugs in the Go version that had escaped code review and testing, and I spotted them because Rust would simply not allow me to express such faulty code. I want more of that kind of enforced validation and sanity-checking for our systems of the future, not less.

But again, that’s just my opinion. The only thing I would say if you are reading this is: if you are in a position to decide between Go or Rust for a new codebase, don’t make the choice without learning about both languages in some level of detail. Only once you have some experience in both you’ll be able to make an informed decision. Tradeoffs!