Rendered at 21:40:08 GMT+0000 (Coordinated Universal Time) with Cloudflare Workers.
Animats 33 minutes ago [-]
I could see migrating from C or C++ or Python to Rust, for various reasons, but for web back-end work Go is a good match. I write almost entirely in Rust, but the last time I had to do something web server side in Rust, I now wish I'd used Go.
The OP points out the wordyness of Go's error syntax. That's a good point. Rust started with the same problem, and added the "?" syntax, which just does a return with an error value on errors. Most Go error handling is exactly that, written out. Rust lacks a uniform error type. Rust has three main error systems (io::Error, thiserror, and anyhow), which is a pain when you have to pass them upward through a chain of calls.
(There are a number of things which tend to be left out of new languages and are a pain to retrofit, because there will be nearly identical but incompatible versions. Constant types. Boolean types. Error types. Multidimensional array types. Vector and matrix types of size 2, 3, and 4 with their usual operations. If those are not standardized early, programs will spend much time fussing with multiple representations of the same thing. Except for error handling, these issues do not affect web dev much, but they are a huge pain for numerical work, graphics, and modeling, where standard operations are applied to arrays of numbers.)
Go has two main advantages for web services. First, goroutines, as the OP points out.
Second, libraries, which the OP doesn't mention much. Go has libraries for most of the things a web service might need, and they are the ones Google uses internally. So they've survived in very heavily used environments. Even the obscure cases are heavily used. This is not true of Rust's crates, which are less mature and often don't have formal QA support.
lionkor 27 minutes ago [-]
> Rust lacks a uniform error type
Rust has practically one error, it's the Error trait. The things you've listed are some common ways to use it, but you're entirely fine with just Box<dyn Error> (which is basically what anyhow::Error is) and similar.
BobbyJo 15 minutes ago [-]
Having many semantic options for error usage is functionally the same as having many error types, except worse.
ViewTrick1002 9 minutes ago [-]
They all convert seamlessly, and the enums make the branches explicit. Don't even need to check the documentation to find which errors supposedly exists like in Go with its errors.Is, errors.As, wrapping and what not.
An easy rule before you make a knowledge based choice is thiserror for libraries, helping you create the standard library error types and anyhow for applications, easy strings you bubble up.
Or just go with Anyhow until you find a need for something else.
Rust does not have three error systems. It has one: the Error trait. io::Error is one of many that implement it (nothing special about it). Errors defined via thiserror also implement it.
“Anyhow” just allows you to conveniently say “some Error” if you don’t care to write out an API contract specifying types of errors your function might spit out.
LtWorf 6 minutes ago [-]
Praising go for how it handles errors, when it's even worse than C where the compiler at least warns you if you're ignoring return values of calls. That's a new one.
amusingimpala75 43 minutes ago [-]
This is probably going to sound generic / repetitive, but my biggest complaint about Rust is the package management situation, which is entirely the result of the developer mindset. I love the ergonomics on the rust side (the functional approach to data types is beautiful), but I’m working on two projects side by side, one in rust and one in go at the moment. The dependency trees are entirely different beasts, with most of the stuff on the go project covered by the stdlib whereas I think the rust project is over 400 despite asking for just rusqlite (sqlite), clap (cli), ratatui (tui), and tauri (gui), the last of which is by far the worst offender but even without it, it’s still close on 100 which is crazy. If there were (and maybe there are, I just haven’t found them) decently maintained alternatives to the rust crates that actually have a sane dependency approach, I’d feel much better. I’m just trying to not shai hulud my system, and the rust-web people seem to want to turn cargo into npm in that regard.
praseodym 6 minutes ago [-]
Note that many Rust libraries consist of multiple crates, which all end up in the dependency graph. This makes the number of dependencies seem higher than it actually is: the separate crates have the same maintainers and are often part of the same upstream git repo.
I agree with the general sentiment though. Rust also has a lot of crates that are stuck semi-unmaintained at some 0.x version, often with no better alternative.
vlovich123 2 minutes ago [-]
Unfortunately the 0.x version has pervaded because of community cargo culting claiming that versioning is easier with 0.x than with major version numbers > 0. Personally I find that hard to believe, especially given packages like Tokio and anyhow (still at v1) make it work and there’s others that are >v1.
That is to say 0.x doesn’t necessarily mean unmaintained, it can also mean “I don’t want to have to think about how to version APIs / make guarantees about APIs). Eg reqwest is very widely used and actively maintained yet is still at v0.13.
repelsteeltje 35 minutes ago [-]
Interesting. I'm not very familiar with Go. What is the equivalent for Tauri in Go's stdlib?
Would it make sense to continue using Go for the frontend and doing only the backend in Rust for your user case?
fatty_patty89 22 minutes ago [-]
wails, there's wails3-alpha which some people said is even better than tauri
repelsteeltje 13 minutes ago [-]
Thanks. Is wails a Go stdlib component, as GP implied or is it third party?
ViewTrick1002 5 minutes ago [-]
> rusqlite (sqlite), clap (cli), ratatui (tui), and tauri (gui)
Does any language, except like Java, exist with a standard library comprising matching that?
Also, keep in mind that Tauri itself is 14 crates, where each one shows up in your build tree.
Why is it worse to import a number of other packages that provide exactly the functionality you need, than to have a large standard library that provides some but not all of the functionality you need, requiring you to still use some large dependencies?
awesome_dude 9 minutes ago [-]
Package management is the bane of nearly every language/technology
Nobody has "solved" it, and I don't think that there will ever be one (never say never, though, right?)
For Go we rely on developers of libraries to adhere to the semver versioning scheme accurately, and we cannot "pin" versions (a personal bugbear of mine)
There is a couple of workarounds - using SHAs not unlike the git commit hash to provide a pseudo version, and, vendoring (which is a cache of known dependencies - which brings with it cache management problems)
I had the misfortune of having to use Python with a virtual env on the weekend - it did not end well, and reminded me why I migrated away from Python.
Look at
Perl (cpan)
Java (maven, gradle)
Ruby (gems)
Go (dep, glide, vgo, modules)
Rust (cargo)
Node (npm, yarn, etc)
OSes too
Redhat (yum, rpm, etc)
Debian (apt)
Ubuntu (snap - god why????)
And so on
OtomotO 29 minutes ago [-]
The stdlib is the place where good ideas go to die.
And then you have httplib3 followed by httplib4.
In other words: I highly prefer the Rust approach.
It doesn't matter a lot whether I rely on the stdlib or another dependency to me.
It's a dependency after all.
People think just because it's the stdlib it's somehow better quality or better maintained, but these are orthogonal concepts.
In the end it depends solely on resources.
Sure, the stdlib may get more of these, but it may also grow fat and unmaintainable...
kayo_20211030 31 minutes ago [-]
If you have a green field, by all means write it in rust. If you have a brown field, and a functional profitable system, rewrite the parts that need rewriting in the original language, whatever that is, and carry on. Make your systems better in small measurable ways, with the language you know and a team you trust to implement it all. Anything else is a wasteful religious argument.
Thaxll 11 minutes ago [-]
I don't see any reasons to use Rust when your team successfully shipped and is confortable with C#/Java/Go ect ...
treavorpasan 5 minutes ago [-]
If anyone one comes and tells me we need to rewrite in a new language from any of those modern languages, other than you are dealing with something cannot wait for GC.
That is a signal that person is lacking purpose in their job or life.
gertlabs 41 minutes ago [-]
I liked Rust before running a benchmark, but the gap between how effectively most LLMs write in Rust vs Go was still surprisingly large to me (especially in agentic harnesses where they can fix the initial environment issues). I've become a pretty big Rust evangelist after seeing that. We've had a lot of success writing batch processing tools in Rust to be called by our existing codebase, but haven't attempted a full production migration... yet.
I will say that many of the issues with Go in the article, especially re: nil handling are increasingly solved by thorough coding reviews with Codex. Better to not have the issue in the first place, sure, but these kinds of security bugs are becoming optional to developers who put in at least as much effort to review and understand code as they put into the initial design and execution.
The weakness of Rust WRT LLMs is compilation times. LLMs code faster and hence spend relatively more time waiting for compilation than humans do, so on reasonably sized projects (e.g. 100k+ lines) Rust's ~10x slower compilation starts showing up as a bottleneck. If you're writing some critical infrastructure it makes sense to pay that cost, but if you're writing some internal service that's not publicly exposed to the internet then development velocity may be a bigger concern. (I'd argue that slow compilation also influences human development velocity, but for some reason developers very rarely try to quantify this.)
Thaxll 32 minutes ago [-]
"services that your organization relies on, that have high uptime requirements, that are critical to your business"
Kind of funny when your Rust service runs on Kubernetes.
nemo1618 20 minutes ago [-]
LLM writing tells are getting more subtle, but they still jump off the page for me, in particular the word "genuine:"
"This is the area where Go genuinely shines, and it’s worth being precise about why"
"the lack of GC pauses is a genuine selling point"
"Humans are genuinely bad at reasoning about memory"
"There are cases where the borrow checker is genuinely too strict"
tbc I don't think the article was fully AI-generated, just AI-assisted. If so, the author did a genuinely good job of it! No one else is commenting on it, so clearly it didn't detract much from the substance. It's just weird that this is becoming increasingly common, and increasingly hard to detect.
pton_xd 15 minutes ago [-]
This is completely off topic now but, "it's worth being precise about ..." is a much stronger AI-ism than the usage of the word genuine.
bbg2401 7 minutes ago [-]
I've noticed LLM writing over the past year has had an unusually high tendency to talk about surfaces and, in particular, substrates. I don't expect LLM generated text to be anything other than rich with clichés. I simply wish we would all demonstrate a better editorial hand so we weren't reading the same voice, over and over.
arccy 33 minutes ago [-]
perhaps the oncall is better if you write your own services, but as an SRE / ops person who has to run other people's services, rust ones just generally seem to be worse: logs that are so verbose but seem to tell you nothing, statsd seems to be the only choice for metrics, contextless errors everywhere, memory "leaks" (more like runaway memory use) that the developers swear are impossible because it's rust, overall just less mature across services written by both in house and oss teams
arjie 31 minutes ago [-]
I do like using Rust quite a bit, but the presence of arbitrary build-time code in build.rs is very risky until we get better at implementing dev-time sandboxing.
geenat 29 minutes ago [-]
If verbosity is a main stickler, this is coming to golang 1.28 which will cut it down drastically:
The "when to enforce it" framing is what sticks with me. Go and Rust agree on safety, concurrency, simple deployment, but Go says "catch it in review" and Rust says "catch it before it compiles." The right answer depends entirely on how expensive a production incident is for you vs. how expensive slower iteration is.
LtWorf 5 minutes ago [-]
> but Go says "catch it in review"
So, in production?
airstrike 5 minutes ago [-]
[delayed]
amazingamazing 32 minutes ago [-]
Rust is great. However in an agentic world go will win. Look no further than incremental build times. This, combined with high token costs mean that for a given application it simply will cost more to to write it in Rust than Go.
This can easily be justified for many usecases, but for your vanilla crud app, do you really need Rust?
Per the article, you are getting 20-50% better more performance with Rust. Not worth it unless your team was already fluent in Rust. Now consider a scenario where your team uses AI exclusively to code, now you are spending more time and tokens waiting around to consume large rust builds. As far as I know this is an inherent property of Rust to have its safety guarantees.
I think Rust makes sense for a lot of cases, but for a small web service, overkill and unnecessary imho. If someone ported their crud app from Go to Rust I would question their priorities.
Again I am speaking more in terms of software engineering economics than anything else. Yes, I know in a perfect world Rust binaries are smaller, performance is better and code more “correct”, but the world is hardly perfect. People have to push code quickly, iterate quickly. Teams have churn, Rust, frankly is alien for many, etc.
nicoburns 8 minutes ago [-]
> As far as I know this is an inherent property of Rust to have its safety guarantees.
From what I've seen, Rust's strictness is actually a huge win for LLMs, as they get much better feedback on what's wrong with the code. Things like null checking that would be a runtime error in Go are implied by the types / evident in the syntax in Rust.
crabmusket 13 minutes ago [-]
> spending more time and tokens waiting around
Can you clarify how you're spending tokens on waiting? My understanding is that the LLM isn't actually necessarily doing anything while a build runs. The whole process end to end may take longer for sure (ignoring things like the compiler catching more errors, that's really hard to factor in) but how does that correlate to more tokens?
amazingamazing 11 minutes ago [-]
> The whole process end to end may take longer for sure (ignoring things like the compiler catching more errors, that's really hard to factor in) but how does that correlate to more tokens?
This. rust emits more information both in its output and the syntax itself more complicated requires more tokens.
natsucks 20 minutes ago [-]
Because the agentic world involves the generation of so much code that gets harder to review, I would think the compile-time guarantees of Rust would make it a better option.
amazingamazing 17 minutes ago [-]
This is true if the token budget and time are not taken into account. In practice though, waiting minutes instead of seconds per build multiplied by prompt and again by change adds up very fast.
nicoburns 32 seconds ago [-]
Incremental Rust builds are almost never minutes (on recentish hardware)
A quick measurement on my web browser project with almost 600 dependencies:
- A clean "cargo check" was 31s
- An incremental "cargo check" with a meaningful change was 1.5s
Building is a little slower:
- A clean "cargo build" was 56.01s
- An incremental "cargo build" was 4s
But I find that LLMs are mostly calling "check" on Rust code.
---
That's on an Apple M1 Pro. The latest M4/M5 machines as ~twice as fast.
natsucks 12 minutes ago [-]
When everyone is armed with Mythos-like hacking ability, it's hard for me to imagine people wouldn't make the tradeoff of security over price.
3 minutes ago [-]
johnfn 25 minutes ago [-]
Can you explain a bit about why token costs would favor Go and not Rust?
amazingamazing 22 minutes ago [-]
Go is more verbose, but Rust have more complex syntax which in practice require more tokens.
The big thing though is because builds are slower, you will end up waiting longer as tests are modified, rebuilt and run. This difference piles up fast.
OtomotO 25 minutes ago [-]
It's a good thing then, that the AI hype is dying outside of ycombinator, the silicon valley and the US
amarant 15 minutes ago [-]
As someone with a background of consulting in the Stockholm based gaming industry for the last decade+, I have to respectfully disagree. Nearly everyone I know is very much on the hype train. And for good reason too! The capabilities are undeniable!
OtomotO 4 minutes ago [-]
As is the hype.
You know, shovels are useful, they are just more useful to the shovel manufacturer than the gold diggers.
But in the end it's a cool tool that made it way easier to dig holes and tend to your garden!
The OP points out the wordyness of Go's error syntax. That's a good point. Rust started with the same problem, and added the "?" syntax, which just does a return with an error value on errors. Most Go error handling is exactly that, written out. Rust lacks a uniform error type. Rust has three main error systems (io::Error, thiserror, and anyhow), which is a pain when you have to pass them upward through a chain of calls.
(There are a number of things which tend to be left out of new languages and are a pain to retrofit, because there will be nearly identical but incompatible versions. Constant types. Boolean types. Error types. Multidimensional array types. Vector and matrix types of size 2, 3, and 4 with their usual operations. If those are not standardized early, programs will spend much time fussing with multiple representations of the same thing. Except for error handling, these issues do not affect web dev much, but they are a huge pain for numerical work, graphics, and modeling, where standard operations are applied to arrays of numbers.)
Go has two main advantages for web services. First, goroutines, as the OP points out. Second, libraries, which the OP doesn't mention much. Go has libraries for most of the things a web service might need, and they are the ones Google uses internally. So they've survived in very heavily used environments. Even the obscure cases are heavily used. This is not true of Rust's crates, which are less mature and often don't have formal QA support.
Rust has practically one error, it's the Error trait. The things you've listed are some common ways to use it, but you're entirely fine with just Box<dyn Error> (which is basically what anyhow::Error is) and similar.
An easy rule before you make a knowledge based choice is thiserror for libraries, helping you create the standard library error types and anyhow for applications, easy strings you bubble up.
Or just go with Anyhow until you find a need for something else.
https://crates.io/crates/anyhow
https://crates.io/crates/thiserror
“Anyhow” just allows you to conveniently say “some Error” if you don’t care to write out an API contract specifying types of errors your function might spit out.
I agree with the general sentiment though. Rust also has a lot of crates that are stuck semi-unmaintained at some 0.x version, often with no better alternative.
That is to say 0.x doesn’t necessarily mean unmaintained, it can also mean “I don’t want to have to think about how to version APIs / make guarantees about APIs). Eg reqwest is very widely used and actively maintained yet is still at v0.13.
Would it make sense to continue using Go for the frontend and doing only the backend in Rust for your user case?
Does any language, except like Java, exist with a standard library comprising matching that?
Also, keep in mind that Tauri itself is 14 crates, where each one shows up in your build tree.
https://github.com/tauri-apps/tauri/blob/dev/Cargo.toml
And Ratatui is 6:
https://github.com/ratatui/ratatui/blob/main/Cargo.toml
Nobody has "solved" it, and I don't think that there will ever be one (never say never, though, right?)
For Go we rely on developers of libraries to adhere to the semver versioning scheme accurately, and we cannot "pin" versions (a personal bugbear of mine)
There is a couple of workarounds - using SHAs not unlike the git commit hash to provide a pseudo version, and, vendoring (which is a cache of known dependencies - which brings with it cache management problems)
I had the misfortune of having to use Python with a virtual env on the weekend - it did not end well, and reminded me why I migrated away from Python.
Look at Perl (cpan) Java (maven, gradle) Ruby (gems) Go (dep, glide, vgo, modules) Rust (cargo) Node (npm, yarn, etc)
OSes too Redhat (yum, rpm, etc) Debian (apt) Ubuntu (snap - god why????)
And so on
And then you have httplib3 followed by httplib4.
In other words: I highly prefer the Rust approach.
It doesn't matter a lot whether I rely on the stdlib or another dependency to me.
It's a dependency after all.
People think just because it's the stdlib it's somehow better quality or better maintained, but these are orthogonal concepts.
In the end it depends solely on resources.
Sure, the stdlib may get more of these, but it may also grow fat and unmaintainable...
That is a signal that person is lacking purpose in their job or life.
I will say that many of the issues with Go in the article, especially re: nil handling are increasingly solved by thorough coding reviews with Codex. Better to not have the issue in the first place, sure, but these kinds of security bugs are becoming optional to developers who put in at least as much effort to review and understand code as they put into the initial design and execution.
Language data at https://gertlabs.com/rankings?mode=agentic_coding
Kind of funny when your Rust service runs on Kubernetes.
https://github.com/golang/go/issues/12854#issue-110104883
So, in production?
This can easily be justified for many usecases, but for your vanilla crud app, do you really need Rust?
Per the article, you are getting 20-50% better more performance with Rust. Not worth it unless your team was already fluent in Rust. Now consider a scenario where your team uses AI exclusively to code, now you are spending more time and tokens waiting around to consume large rust builds. As far as I know this is an inherent property of Rust to have its safety guarantees.
I think Rust makes sense for a lot of cases, but for a small web service, overkill and unnecessary imho. If someone ported their crud app from Go to Rust I would question their priorities.
Again I am speaking more in terms of software engineering economics than anything else. Yes, I know in a perfect world Rust binaries are smaller, performance is better and code more “correct”, but the world is hardly perfect. People have to push code quickly, iterate quickly. Teams have churn, Rust, frankly is alien for many, etc.
From what I've seen, Rust's strictness is actually a huge win for LLMs, as they get much better feedback on what's wrong with the code. Things like null checking that would be a runtime error in Go are implied by the types / evident in the syntax in Rust.
Can you clarify how you're spending tokens on waiting? My understanding is that the LLM isn't actually necessarily doing anything while a build runs. The whole process end to end may take longer for sure (ignoring things like the compiler catching more errors, that's really hard to factor in) but how does that correlate to more tokens?
This. rust emits more information both in its output and the syntax itself more complicated requires more tokens.
A quick measurement on my web browser project with almost 600 dependencies:
- A clean "cargo check" was 31s
- An incremental "cargo check" with a meaningful change was 1.5s
Building is a little slower:
- A clean "cargo build" was 56.01s
- An incremental "cargo build" was 4s
But I find that LLMs are mostly calling "check" on Rust code.
---
That's on an Apple M1 Pro. The latest M4/M5 machines as ~twice as fast.
The big thing though is because builds are slower, you will end up waiting longer as tests are modified, rebuilt and run. This difference piles up fast.
You know, shovels are useful, they are just more useful to the shovel manufacturer than the gold diggers.
But in the end it's a cool tool that made it way easier to dig holes and tend to your garden!