Comment by tptacek
19 hours ago
This is a weird document that is simultaneously trying to serve as a migration guide and an advocacy document for Rust.
Ultimately, if you have to ask, the Rust vs. Go consideration boils down almost completely to "do you want a managed runtime or not". A generation of Rust programmers has convinced itself that "managed runtime" is bad, that not having one is an important feature. But that's obviously false: there are more programming domains where you want a managed runtime than ones where you don't.
That's not an argument for defaulting to Go in all those cases! There are plenty of subjective reasons to prefer Rust. I miss `match` when I write Go (I do not miss tokio and async Rust, though). They're both perfectly legitimate choices in virtually any case where you don't have to distort the problem space to fit them in (ie: trying to write a Go LKM would be a weird move).
The Rust vs. Go slapfight is a weird and cringe backwater of our field. Huge portions of the industry are happily building entire systems in Python or Node, and smirking at the weirdos arguing over which statically typed compiled language to use. Python vs. (Rust|Go) is a real question. Rust vs. Go isn't.
Exactly. 95% of programmers are application programmers - they ship software used by regular users. I think it's insane to use a non-GC language for most of those cases. Manual memory management is mentally taxing and it's easy to make catastrophic mistakes. The marginal benefit from it is just not worth it unless you're making games or a trading system.
5% who write tools or other "infra" layer for the other 95% to work on top of maybe need that level of control over memory. It doesn't make any sense to me to sign up for that complexity unless you really really need it.
Maybe I'm misunderstanding something but non-GC language doesn't mean you have to do memory management manually? I mean, for example, in Rust (or modern C++), it's basically automatic. There is no mental tax or catastrophic mistakes as far as I know.
Ok.
https://rust-unofficial.github.io/too-many-lists/
I'm not saying Rust is worse than Go. It obviously isn't. But this argument that Rust's memory management isn't more cognitively demanding than Go's memory management --- that isn't true.
5 replies →
You seem to imply that it doesn’t have any cost. It does. You have to make decisions and, in the case of C++: sometimes you have to deal with a lot of really ugly code to make it “automatic”. And if you really have to count bytes and carefully manage stack sizes because you are writing code for a constrained device, you have to pay even more attention than you would in C.
GC’ed languages have memory related challenges too. But it simply isn’t true that these are on the same order of difficulty as the difficulties that do arise in C++.
1 reply →
Or it could be insane to pay the cloud memory costs when you have tools that can write rust for you.
What "cloud memory costs"? Most Rust code is an informally-specified version of the old Python reference-counting GC. That's how you're supposed to write it, with clone() everywhere, and then dropping down to optimize. You can do the same thing with Go in the other direction by writing an allocator.
People believe a lot of weird things about these languages.
This post is specifically about backend development, where you're not shipping software to regular users.
This is just a matter of perspective. Backend IS being "shipped" to user via the API be it go or rust and inevitably the details and behavior do leak out to end user.
> and it's easy to make catastrophic mistakes
such as ... ?
The use of LLMs has caused Rust usage to explode.
If youre not writing the code yourself and vibing away which I think most people generally are despite the disdain around here then why would you not choose the "more performant language" (I know that isnt necessarily reality but it is a common perception).
Go's managed runtime is less valuable when the LLM is perfectly happy to slap a bunch of stuff together for you to and approximate it and doesn't complain at all when writing async rust despite some of the rough edges.
Correction: The use of LLMs has caused every major language usage to explode.
And as mentioned in other comments, Rust slow compilation can be detrimental to LLMs + fast iteration speed. And it's not just speed, Tauri takes 20GB of disk space to compile. It's bonkers. This is npm/js ecosystem all over again but slower.
Another reason to pick Go if you're leaning on LLMs is the standard library. Often you can do more work with fewer dependencies.
I'd rather leverage world class engineers paid by Google to maintain dependencies for me than try my luck with half a dozen of 0.x crates. Plus stdlib APIs can (and are) versioned just like third party dependencies.
Fully agree with this. We use Rust in an enterprise setting for building web app backends and the experience is painful. A lot of crates just seem like someones side project. Too many ways to do things leads to bike shedding in PRs. Compile times are atrocious and can take like 30 mins to build.
Honestly using Go would have got us to the same point much quicker, with code that is much easier to review.
I like vibe coding but I am sceptical that a vibe coded runtime in Rust would be as awesome as the Go runtime which is written with deep expertise of Unix software and threading and many low level details that are subtle and do depend on global properties of the code to work flawlessly. It makes sense you can crank out Rust with an LLM if you know what you are doing, but if you want a GC type thing or preemptive scheduling across an N by M threading model, then you are competing against some very good code.
> the Go runtime which is written with deep expertise of Unix software
Go has no mmap(), import a 3rd party dependency for that and you'll get a segfault the very second you do a mistake.
Python has an mmap module which will catch many memory errors and present them as exception rather than causing a CVE.
4 replies →
I agree that agents make Rust a lot more tenable for less "kernel-and-browser"-demanding tasks than it was 4 years ago, but I do not agree that they eliminate the "managed vs. unmanaged runtime" question, and to the extent they influence any of this decisionmaking at all, you have to accept the notion of not reading the code. If you're reading it, it matters that Rust makes you do bookkeeping that managed runtimes avoid.
By that reasoning, we should all be vibing away C code. It's the most performant and efficient language out there, there's a ton of code out there the LLMs were trained on, and the complex logic of memory management is abstracted away by the LLM so you don't need to think about it.
Most people are not doing that though. There's probably a good reason, and it applies to other languages too.
There is a good chance that your vibe coded C program segfaults immediately upon running and contains lots of subtle logic errors, all of which requires many iterations (finding issues at runtime) before you program runs as expected.
With Rust, you'll likely get many compilation errors, but if your syntax is correct, compilation errors will be few, and your code will almost certainly just work.
1 reply →
In order to use C you need to actually understand it, also toolchain is more complex etc. Which makes it a no go for 99%.
Rust is so safe that anyone can vibe it without any idea what is going on there. Which is basically what is happening here.
And why rust is more used than go for vibecoding? Mostly because of hype and performance gains which 99.9% of projects do not need.
1 reply →
> The use of LLMs has caused Rust usage to explode.
Rust had a "vibey" community long before vibecoding. In particular, it's long been fairly non-serious about yolo importing a bunch of crates to solve things (since the standard lib is small) which is kinda the same problem as having all those things just vibecoded. Either way, most projects weren't reading all of that other code!
For the vast majority of software you want a managed runtime.
Some of the problems Rust “solves” are problems you shouldn’t be having in the first place because we mostly write software that doesn’t need direct control over memory. Borrow checking isn’t something you want to have to deal with - it is something you have to accept when you have chosen to manage memory. That choice has a high cost that cost never gets paid off in most projects that could work just as fine with managed memory.
I’m a Go programmer, but this article reminded me that I should have more experience with Rust. From my perspective Rust seems a bit less practical. The standard library lacks support for cryptography, for instance. The compiler is slow, which is a productivity killer. Overall concurrency seems like a bit of an afterthought. Again.
What makes me want to try Rust in production are things like option types. Those would be nice to have in any language. Any issues that can be caught by the compiler are a plus. Getting rid of nil would also be a plus, but to be quite frank, I don’t experience that many nil pointer errors.
The author does nod to the static analysis tools for Go. Yes, they are not part of the compiler (for good reason), but they do a pretty good job in practice. So you get more than the compiler can promise at a fraction of the cost (measured in build time). That’s a much bigger deal for actual developers than we generally give it credit for.
Then there’s the stuff that makes me less convinced in terms of arguments. For instance the fact that Go didn’t have generics early on and that the standard library doesn’t use them. Generics were not as important as people thought they were. In practical reality. The fact that the standard library doesn’t make wide use of them is not a weakness, it shows restraint. They didn’t go overboard and prematurely plaster generics all over the place as soon as the language supported it. This is the kind of restraint you want to see. Remember how horrible Java was after everyone started abusing generics? A brief generation of software that was significantly worse, and less maintainable resulted from this exuberance. For the ultimate example of what happens when you give people every feature they wish for: look at C++. It´s not a very good language because it is many languages. Just because there are standards and recommendations doesn’t mean that all code magically gets rewritten to a narrower definition of the language. It means that we accumulate intermediate forms. I expect people who are interested in languages to understand these dynamics.
Rust's stdlib is small, Go took more of Python's "batteries included" strategy.
So in that sense it seems like a category error to try to look for crypto stuff in the standard library. Of course this brings the well known problem of "okay, but then which one should I use?". Nowadays this is largely solved by a few web searches and LLM queries, and people are quite helpful at https://old.reddit.com/r/rust/ .
Go was shaped by the needs of Google, Rust is a wildly successful amazing experiment in programming language and compiler design that really got out of hand :) (A bit like JavaScript! Or even C#! Or Python. Same growing pains (async/await!), but arguably on different levels.)
Have you argued yourself to "it's a bad thing that the Go standard library has a cryptography library"?
Aren't you overlooking the main point of the article?, the reason they migrated:
> concurrency — eliminating data races essentially, which we had before. Really gnarly bugs
> this is the one teams report most enthusiastically. The classes of bugs that survive go test -race and reach production (data races, nil dereferences, missed error paths) just don’t compile in Rust. Oncall rotations are typically very boring after a Rust migration. ...
> I hadn’t had to chase down a crash, or some weird multi-threaded race condition, or some of these other things which actually consumed a huge amount of my time before.
(They say at InfluxDb)
That's not a Rust vs. Go slapfight? Instead, sounds like a good judgement to me
Us Node folks adapted typescript because we wanted static compiled types.
I wish TS had more of a runtime. The only thing I'm jealous of with regards to python is how seamlessly you can do JSON schema enforcement on HTTP endpoints. The Zod hoops are a constant source of irritation that only exists because the TS team is dogmatic.
express-zod-api works well for me https://github.com/RobinTail/express-zod-api I'd say about as well as anything Python
I think Typescript is a perfectly cromulent language. I don't know it well but would seriously consider it for any problem that had a shape that admitted a dynamic language. There's a lot to be said for using dynamic languages, too!
Every non-runtime language is dynamic after being compiled to x64 machine code!
It is illusions and lies all the way down the instant the compiler finishes its job.
Check out Perry the TypeScript compiler to native code
It sounds like you should try ocaml
Indeed, if I were proposing contributions to the Linux kernel, or any other kind of systems development, I'd probably be considering Rust. For backend services, the decision is between C# and Go (with the latter being the favourite).
I think I'd be ok with node via purescript? But in general I think rust and go people should join forces against the evils of dynamic typing. Isn't type hinting finally considered best practice now? I think that is effectively an admission that it was a defect. And even with good ginting it is still worse than inference. Inference can let plenty of code go untouched on type changes, while still protecting against unindended type changes.
> Ultimately, if you have to ask, the Rust vs. Go consideration boils down almost completely to "do you want a managed runtime or not".
You don't need a garbage collector which is perhaps half of the Go Runtime when you're using Rust.
You can also bolt on a few crates and get ~95% of what you'd get from Go's runtime.
Go has the best runtime in the world. I'll give it that.
But this is not the only reason...
You obviously don't need a GC when you're using Rust, because Rust doesn't plausibly have one.
Right, so you don't need a large portion of Go's runtime benefits, because you have a far better version of it already, zero cost abstractions and TRUE memory safety, not pretend memory safety behind a -race detector with zero compiler guarantees...
1 reply →
> the Rust vs. Go consideration boils down almost completely to "do you want a managed runtime or not".
That's not really something I care much about. My beefs with Go are 90% about the syntax of the language itself, and it's weak (compared to Rust) type system.
When it comes to a managed runtime, for most tasks, I generally don't care if my language has one or not. For some tasks I do, but there are not many of those tasks, and so this question is mostly irrelevant to me when deciding Go vs. Rust.
I don't really get where you're seeing that the predominant Go vs. Rust debate is about the runtime. IME it's the subjective stuff about the languages themselves, and their ecosystems and communities.
> The Rust vs. Go slapfight is a weird and cringe backwater of our field.
::shrug:: I dunno, I mostly stay out of it and just use Rust, and I'm happy and avoid the drama. I've written a little Go here and there, didn't really like it, and moved on.
That's totally fine. I don't get why people moralize this stuff. Both of these languages are rounding errors compared to the dynamic languages.
I think people do this for every language. It becomes a part of their identity, and then they have to defend it. I used to do that too, long ago, but I don't have the time or energy for it for the most part, and find it boring, so that $LANG-user-as-identity bit of my has fallen by the wayside.
I don't think it's about adoption levels; sure Go and Rust are tiny compared to JS/python/etc. It's emotional, not about who has the most users or who can even plausibly get there.
Because it triggers the "feeling of other" when someone is so close yet so far ideologically.
I'm sure you know this joke about dogmas :)
https://news.ycombinator.com/item?id=26624442
In some sense this is the same as the NIMBY/YIMBY question. There are perfectly valid reasons to want to live like Spacers do on Aurora, yet many prefer the caves.
It feels like you’re upset because your favorite language has objective flaws that people are pointing out. You’re also trying to minimize people’s lived experiences and pleading with them to stop pointing the flaws out.
Sure, Go is better than Python in some things. But developers deserve the best. We deserve not to have to deal with Go’s quirks, idiosyncrasies and design mistakes.
Well there's also the:
- Rust vs Swift slapfight
- Rust vs CPP fight (which is bit like Jake Paul vs. Anthony Joshua).
Strangely it's always Rust v something. It's almost as if they're hell-bent on Rust maximalism.