Go or Rust? Just Listen to the Bots
cybernetist.com
cybernetist.com
If I'm prototyping or experimenting, I'm much more productive in Go. If I have a well-specified protocol or something that works that I want to be faster, more secure, or importable via C ABI, I'd go Rust.
In practice this means I almost never use Rust.
Node is awful with lots of connections. Go gives me way fewer bugs, easier to properly trace, static typing is a blessing, etc.
With a db that can handle thousands upon thousands of connections, Go trounced Node in my experience
For fe, I use ts with htmx for any server side rendering. I got very deep into nextjs enough to consider myself competent but code bloat and dependency breakages just got me off it
For backend/control planes like things nothing has come close to Go for me. It isn't perfect in any one axis, but has a bit of everything I need mixed (fast build speeds, CSP style concurrcy for managing orchestration related workflows, reasonably good typing, and runtime speed), well rounded stdlib, fewer dependency breakages and soon.
But that also means that it is not necessary for pretty much every company out there except the biggest ones.
Rust is cool for interops though: you talk about the OS, but it's not just that, it's also integrating with other languages in a way managed languages can't do: you can use Rust in a Python app like you'd use C, and you can speed up critical section of your node App with it as well[1], this is where Rust shine. Not in competing with Go in online popularity contexts.
Go is easier for onboarding, it's fixed the major issues people have had with it - it has modules, it has generics. It's easy to package a binary versus deal with having a Python venv.
Go is just the best common denominator and that's what the majority of people need. I really feel that people want to use Rust because it's interesting and fun, not because it's really the better tool for the job. The vast majority of applications can use GC and are not resource constrained by Go's runtime or binary size.
Instead of figuring out what's the package manager/virtual env wrangler du jour when installing my stuff to a new server after 2+ years of not touching it (Poetry is the current leader I think?) I can just compile the Go program with the correct arch on my local computer and scp it to the server.
As for Rust, it just requires more upfront cost, but makes you consider potential failures at every step. Debugging production code isn’t fun, fuzz tests aren’t enough to assure quality to the extent Rust’s type system can. I trust rustc much more than I trust myself or other devs. If the code passes rustc, and the type semantics are correct, I’m 3/4 certain the code is correct, that’s a very high watermark, albeit at the cost of the upfront effort to satisfy the type constraints. Much more efficient in terms of dev time than debugging Python or Go at runtime.
Anyway, one can easily run many Python packages on GraalVM Truffle for direct interfacing with Java, Ruby, R, and via PyO3 with Rust, for which you have the native Polars data frame library, which all cover a good chunk of Python programs. Rust also teaches one to do proper ownership accounting for the variable bindings, great for C++ devs and for heap escape analysis by inspection for Go devs alike. Lots of Go bugs result from lack of understanding of ownership and implicit reference binding as opposed to copy and move semantics. Some of that was now “improved” with Go 1.22 for closures in loops.
First OSS version of .NET was released 8 years ago.
Java is much higher level and much more OOP focused language than C# of today, which is multi-paradigm and exposes a lot of low-level features when needed, and is implemented under the hood way closer to the likes of C++ and Rust.
The difference in quality is dependent on the context. If a company is a pure Java shop that lives and breathes Apache projects - sure. Not so much or opposite otherwise.
https://web.stanford.edu/class/cs240/old/sp2014/readings/wor...
I like the syntax and type system more in Rust, but at the end of the day the language are pretty similar in terms of developer experience if you're doing back end stuff[1].
(Fun fact I learned Rust and Go roughly at the same time in 2015, and Go's tutorial was a big help for my understanding of concurrent programming in Rust, with channels and mutexes, for someone who came from a JavaScript background and had never been exposed to threads before).
[1] A cool thing about Rust is that you can use it to learn new stuff that aren't web back-end, but that's a good reason to pick it for side projects, not for using it as a company.
Edit: four downvotes in three minute? I must have say something offensive…
I've been on both sides, I leaned Rust very early and it took me a while to even understand what lifetimes were and wth was `Copy` and `static`, but after that I've been onboarding complete beginners at several companies and they got proficient very quickly with some guidance from me for key concepts.
Rust isn't hard, it's just has a few concepts that you need to understand otherwise you're just confused by everything you encounter. But to me wasn't not too different from the effort it took me to understand "wtf are prototypes" when learning JavaScript 15 years ago.
When you come from a certain language paradigm and you're learning a language with another paradigm everything sounds so confusing at first, even though the difference aren't actually that big in reality. But you need to be able to overcome the difference before you see the similarities.
I couldn't teach _myself_ Rust in a week.
Yes, if you're making something where being Correct is a hard requirement - Rust is perfect. But you do need to acknowledge that there is a definite learning curve and the average Job Coder (works from 9-5 and doesn't think about it on their free time) isn't cut out for Rust.
If your team is hand-picked 10x coders, Rust is again by far the best choice. It's got fancy PL bells and whistles that keep the dopamine running for experienced people =)
> I couldn't teach _myself_ Rust in a week.
Autonomous teaching is supposed to be harder than with a tutor in any domain so it's not particularly surprising ;).
> But you do need to acknowledge that there is a definite learning curve
I don't like the “learning curve” phrase for Rust, because the curve itself is actually fine.
But before you can even enter the learning curve there's a significant step to cross. It's not particularly difficult, but it's all about theory and concepts. It's like high-school level trigonometry, it's not particularly hard, but it's still something a bit dry and that needs motivation to learn.
With a teacher and assignments, most people can do it, but without it you really need to make the effort of understanding the core concept (Ownership, borrowing, Send and Sync, + heap and stack if you don't know about it before hands + what are threads, data race and locks[1]) before you can even start to get to the fun part of learning a new language.
> and the average Job Coder (works from 9-5 and doesn't think about it on their free time) isn't cut out for Rust.
Without an external motivation source, the average developer has no reason to have the motivation to cross this learning step.
But as part of my job, I've thought Rust to average Joe in a week and they became productive quickly. I'm sure I could teach you Rust in a week ;).
[1]: the deadlock empire is an excellent learning resource for that one.
Sure, but you can teach yourself Go in a couple of days, likely having running code from the get go. I think with Rust you will have more frustrating interactions with mr. compiler in the beginning.
> Edit: four downvotes in three minute? I must have say something offensive…
It's because it's not "a few days of learning" with Rust.
And then I've been working in Rust with beginner and mentoring them while they learned Rust, and I can assure you that the difficult part that most people struggle with is just half a days of learning actually[1]. Then you put in practice with exercises, to familiarize yourself with the syntax and the std lib, for a few days and you're ready to code.
The difficulty is to overcome the first step of assimilating concepts, that you need to unlock the next steps. If you skip the concept phase, then you can remain confused for a while I guess.
[1]: I've just check my slide deck, Ownership + Borrowing + Arc/Rc + RefCell/Mutex + Lifetimes + Send + Sync, the entire package of Rust hardcore concept that everybody struggles with, fits in 63 slides, with the exercises, and I usually cover it in half a day. And it's accessible to pretty much everyone without prior Rust or C++ experience. I even re-explain what a thread and what the heap are.
> This project has come into existence over the past couple of weeks of hacking late nights and early mornings. At times I felt like I was building a plane during take-off – especially the Rust code parts which I was literally picking up along the way. It’s been a tremendous fun experience I’ve really enjoyed. It made me appreciate both Go and Rust in different ways as similar yet so different programming languages.
Reading the news used to have a bad effect on my mood as well, and my life is much better since I've stopped doing it daily.
Wish you the best.
Now if you said you need a systems language, a scripting language, an imperative language, an object-oriented language, a functional language, a logic language, a matrix language, and a lispy language in your toolbox, then sure - that makes sense. But in my experience that is not what people are saying, and that's why I'm pushing back on this way of thinking.
Why do so many go devs feel the need to make statements like this. Go has issues, the are well known and easy to work with/around. Every language has these, every single one.
Also GO, and rust (and zig for that matter) have all sort of found their lanes at this point. Candidly the constant comparisons between the two (when they are much more complimentary) is getting tired.
- Acknowledge the common criticism
- Defeat it with appropriate common retort, or make a small concession
- Proceed with the meat of the argument with your most common opponent "disarmed"
Is it? Because I dont see JS or python apologists? Did I miss a corresponding lament about rust compile times in the article?
At least for Python it's some combination of: I know Py3 was a nightmare and packaging in general is a dumpster fire, testing is a constellation of incompatible tools and practices, MyPy and progressive typing is an embarrassing half-baked mess, and deployment is only really possible when you bundle an entire system image into a container— but hey, developer productivity right?
Also bring up the GIL, and you'll be told how Python is implementation-agnostic.
Like with Python and ML.
The optimal amount of bullying towards Go and its proponents is always “more”.
At this time, due to the social integration of technology the number of people who interact with development has far out paced the number of people who enjoy development.
> they are much more complimentary
If you hate writing code but do it for your job, then you are going to really hate writing code in two different languages with their own syntax and paradigms.
Also, nearly all programming language projects want to be the “everything language” so essentially any language is a fine choice and what it really comes down to is the people who enjoy the work develop “tastes” and “preferences” that they treat as dogma when defending their language of choice.
Imagine bob ross with only one color could still make something magnificent, but what could he do with two colors? You can't have Burnt Umber without some Phthalo Green..
Turing completeness is about computational equivalence. That, fundamentally, any Turing complete language can perform the same classes of computations as any other. It says nothing about substitutability of one language for another within any other context.
I don't wish for this, but sometimes I wonder how different the industry would be today if dev salaries had remained in "respectable but nothing amazing" territory.
Maybe it's just nostalgia goggles, but when I was getting started ~35 years ago, I think it was rare to run into someone who hated writing code but did it for their job. There were other much more profitable jobs for people who were looking to be paid as well as possible for work they hated.
1. Team uses some interpreted language. This language is fine for most of their work, but causes performance problems and/or the team needs to do something performance sensitive.
2. Someone on the team proposes Go, often because it solves the performance problem - and is very simple to use. This proposal invites suggestions from the organizations programming language experts leading to "let's use lang X" suggestions. Often these suggestions have recommendations based on advanced programming language features such as high-order types, functional paradigms etc.
As Rust has been somewhat popular for backend services, you will find many suggestions of "let's use Rust." These discussions can often be less than civil. As I've aged - I've moved closer to the advanced language features camp - but I'd doubt that this is actually beneficial for productivity. It took me 3 attempts to learn the language and 5 years for Rust to feel productive - now it's my preferred language for side projects. Go took less than a day to pick up.
Rust, on the other hand, is a borderline research language that was built to support Servo, a web browser backend— literally among the hairiest of sofware engineering problems in existence. It gives you a lot of "safety" but at the cost of having to consider issues that most developers never think about.
This is not to say that Go is for dumb programmers and Rust is for smart ones or anything of that sort— just that despite years of evolution, both carry the DNA of their inception, and it shows.
As a very experienced engineer, I like the idea of Rust being a go to for all problems. 10 years ago - I would have hated its complexity and cursed the TL who forced it on my project.
Go ahead and say it; I don't mind being the dumb programmer who gets shit done.
After all,
> Rust, on the other hand, is a borderline research language
It's ironic that the "smart" programmers are using their new and novel language to mostly rewrite existing stuff, while the "dumb" programmers were delivering new and novel shit using the "dumb" language.
If you stop learning just because you've mastered a language and learning the language was not your actual goal, you've failed. You should continue learning by applying the language to solve problems, which, unless you solve the same things over and over again, offers plenty of opportunities for continued learning.
This is the bit people keep overlooking (maybe intentionally). Yes you, polyglot coder who knows 15 different programming languages and has 15 years of experience on the field can learn Rust in an afternoon and do a flawless solution on Advent of Code with it while learning.
But 99% of the people working in software (you know, all of the people outside FAANG and F500 companies) know exactly one language and have no interest in learning a new one, especially one that's really complex and full of fancy features they don't know what to do with.
Also, was Googling how you execute two things at once then wait on both in Golang, and https://www.reddit.com/r/golang/comments/15xp94w/asyncawait_... came up. This is honestly how I judge ease of use, how simple are answers to simple questions. The agreed-upon response was to use a library.
What you may be getting at is that in an environment like Node.js, where everything runs in a single OS thread and there is no parallelism, there's a reduced need for coordination features like channels (or mutexes), because it's safe to mutate shared memory. But that too is orthogonal to `async/await`: the Python library gevent, for example, uses ordinary blocking function calls while running concurrent code in a single OS thread, making it safe to mutate shared memory; and conversely, C# allows `async/await` to be executed across multiple OS threads, making it unsafe to mutate shared memory.
One implication of async/await is that you need some kind of greenthreading or thread pool because you really don't want to spawn OS threads for it. In JS it's an event loop, Python and (I think) Rust have that too now as a lib, and Golang already has its own greenthreads.
And btw, the reason JS doesn't have threading is because for those applications, you don't need fast communication between parallel tasks like the things Golang is made for. NodeJS supports subprocessing, and the tasks will probably not talk to each other at all, though there's IPC if you really want it.
Go brilliantly borrowed ideas from Limbo, Oberon-2 and Newsqueak. Throwing that away by polluting with async/await would be reason for riot imo.
They wanted to do it in a way that's useful and practical for the use-cases Go is best suited for.
(Still haven't needed generics in any of my Go projects)
This is a common conceit when writing for the sort of audience who might, for example, nitpick something as utterly uncontroversial as an author's disclaimer acknowledging common criticisms of a language they enjoy working with.
tl;dr: Literally because of people like you :)