14 ms·
Migrating from Go to Rust
- amusingimpala75 4mo agoThis 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.
- repelsteeltje 4mo agoInteresting. 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 4mo agowails, there's wails3-alpha which some people said is even better than tauri
- repelsteeltje 4mo agoThanks. Is wails a Go stdlib component, as GP implied or is it third party?
- fatty_patty89 4mo agotauri isn't stdlib and neither is wails
- tredre3 4mo agoGo's stdlib has none of the things GP listed. No sqlite3, no ratatui, no cli (though there is `flag` if it's enough for you), and no tauri equivalent in its stdlib. Those would be go-sqlite3, bubbletea, cli or cobra, and wails. Charitably, I think OP meant to say that in the rust project only four dependencies were added and that caused 400 transitive dependencies to be pulled. Adding the four Go equivalent will still result in 10x less packages being pulled. It's a culture problem, Go authors prefer solutions that are self contained, rust authors embrace the culture that gave us left-pad. But, at least in GP's case, it's not a stdlib problem. Not one solved by Go, anyway.
- OtomotO 4mo agoThe 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...
- deleted 4mo ago[deleted]
- desmaraisp 4mo agoThat's an interesting viewpoint, but one I've noticed is less prevalent in other languages. The c# guys at microsoft created an enormous stdlib, and the overwhelming majority of it is pretty good. The outliers being of course older stuff they've never really had time to upgrade. And they don't seem to be afraid to deprecate stuff, every major version brings a couple of minor breaking changes. But it all seems to work out just fine somehow
- sieabahlpark 4mo ago[dead]
- CharlieDigital 4mo agoC# massive standard library and first party libraries means much, much fewer external dependencies and these libraries are managed by a team of paid, professional engineers. Highly, highly underrated.
- amusingimpala75 4mo agoI’m not arguing on quality of the library, I’m arguing on not getting pwned by the sheer number of transitive dependencies
- 4mo ago
- JuniperMesos 4mo agoWhy 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?
- pier25 4mo agoFor example, security. See all the supply chain attacks from the past couple of years.
- awesome_dude 4mo agoPackage 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
- corndoge 4mo agoNix solved it. Languages could choose to adopt Nix as their packaging system.
- tadfisher 4mo agoIt did and didn't. Nix tools for building language-specific packages almost always wrap the language build tool/package manager. This can be easy or hard, depending on how onerous the build tool is for vendoring libraries. What Nix and build tools need to agree on is a specification or protocol for "building a software dependency tree". Like, I should be able to say 'builder = cargo' in a Nix derivation and Cargo should be able to pick up everything it needs from the build environment. Alas, there is simply far too much tied up in nixpkg's stdenv for this to be viable, so we have magic stdenv builder behavior via hooks when a build tool is included in nativeBuildInputs.
- awesome_dude 4mo agoI think one of the key problems too is that a system level dependency is managed by people dedicated to ensuring the chaotic nature of the package they are responsible for conforms to the way the OS they are maintaining for has proscribed. There's no real way to do that at a language level - we cannot have "Go has determined the package you are trying to fix has not met the versioning requirements proscribed so you cannot submit the patch to fix it" What language dependencies do is what OSes would think of as "unofficial versioning" that is, an OS will let you install and run an unofficial version of some lib (we've all been there, right, multiple versions of some core library because one doesn't work with whatever you are trying to install), but they will not manage it at all.
- praseodym 4mo agoNote 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 4mo agoUnfortunately 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.
- nicoburns 4mo ago> claiming that versioning is easier with 0.x than with major version numbers > 0 I think it's less that versioning is claimed to be easier with 0.x versions, and more that some people have got into their heads that 1.0 signals either "permanently stable" or "no new versions for several years" and they don't want to commit to that yet. I do wish more crates would 1.0 (and then 2.0, etc).
- J_Shelby_J 4mo agoThere is good reasons to break out projects into multiple crates. It makes reusing functionality elsewhere easier. It makes it easier to reason about behavior. It makes it easier for LLMs to understand (either working within the crate or consuming as an api surface.) So you end up with projects that have multiple crates inside the same workspace and it really blows up dependency count.
- nicoburns 4mo ago
- ViewTrick1002 4mo 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. https://github.com/tauri-apps/tauri/blob/dev/Cargo.toml https://github.com/tauri-apps/tauri/blob/dev/Cargo.toml And Ratatui is 6: https://github.com/ratatui/ratatui/blob/main/Cargo.toml https://github.com/ratatui/ratatui/blob/main/Cargo.toml
- PyWoody 4mo agoPython has sqlite3[0], curses (tui) [1], and tkinter[2] in the stdlib. [0] https://docs.python.org/3/library/sqlite3.html https://docs.python.org/3/library/sqlite3.html [1] https://docs.python.org/3/library/curses.html https://docs.python.org/3/library/curses.html [2] https://docs.python.org/3/library/tkinter.html https://docs.python.org/3/library/tkinter.html
- ViewTrick1002 4mo agoRight. The famous stdlib where once good libraries go to die so you instead depend on the latest community replacement choice. Also argparse for Clap: https://docs.python.org/3/library/argparse.html https://docs.python.org/3/library/argparse.html
- dwattttt 4mo agoTo highlight the problem for Python: Python's standard library has getopt, optparse, and now argparse. I don't think they set out to offer 3 argument parsing libs, one of which is marked superseded, but here we are.
- chlorion 4mo agoAnd ironically with the exception of the python sqlite3 module, the rust alternatives are much higher quality, IMO. Does anyone even use tkinter in modern times anyways?
- gertlabs 4mo agoI 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. Language data at https://gertlabs.com/rankings?mode=agentic_coding https://gertlabs.com/rankings?mode=agentic_coding
- logicchains 4mo agoThe 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.)
- sieabahlpark 4mo ago[dead]
- J_Shelby_J 4mo ago10x slower is like an extra second, if that, for compilation times for the sizes of changes an agent like codex makes.
- Havoc 4mo ago>The weakness of Rust WRT LLMs is compilation times. That's a more tractable problem then basically anything else around LLMs and programming. We're definitely getting more cores in the avg machine judging by roadmaps & leaks
- arccy 4mo agoperhaps 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
- Animats 4mo agoI 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.
- iknowstuff 4mo agoRust 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.
- tptacek 4mo agoHe's not making that up; in practice, you're going to run into and need to make mental space for the idiosyncrasies of multiple error frameworks.
- amazingamazing 4mo agoRust 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.
- OtomotO 4mo agoIt's a good thing then, that the AI hype is dying outside of ycombinator, the silicon valley and the US
- amarant 4mo agoAs 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 4mo agoAs 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!
- Thaxll 4mo 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.
- jabl 4mo agoWhich in turn relies on a stack largely written in, shock and horror, C, such as the Linux kernel, libc, openssl, nginx, etc. etc. Even if you believe language X to be the bees knees, are you going to stop using it until everything below it in the computing stack has been rewritten in X? Of course not.
- kayo_20211030 4mo agoIf 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 4mo agoI don't see any reasons to use Rust when your team successfully shipped and is confortable with C#/Java/Go ect ...
- treavorpasan 4mo agoIf 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.
- dbdr 4mo agoGC pauses are not the only reason. At the very least, raw compute performance and lower memory usage are also valid reasons in some contexts.
- arjie 4mo agoI 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 4mo agoIf verbosity is a main stickler, this is coming to golang 1.28 which will cut it down drastically: https://github.com/golang/go/issues/12854#issue-110104883 https://github.com/golang/go/issues/12854#issue-110104883
- p2detar 4mo agoThat actually looks great. Thanks a lot for the link.
- nasretdinov 4mo agoBeing able to just return {}, err when returning an empty struct from a function sounds really exciting and encouraging to use pointers less, which is really good for nil safety if anything
- joaohaas 4mo agoI know general consensus on this is that it is good, but I hate this. The fact that both assignments do completely different things (with the map one doing heap allocs!) is insane. This would've been much better if it only allowed for anonymous structs. var A string = "A" type Foo struct { A string } var a Foo var b map[string]string a = {A: "abc"} b = {A: "abc"}
- ngrilly 4mo agoYes, I'm so happy it has been accepted. It will particularly useful to pass named parameters to functions.
- treavorpasan 4mo ago[dead]
- nemo1618 4mo agoLLM 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 4mo agoThis 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.
- deleted 4mo ago[deleted]
- bbg2401 4mo agoI'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.
- tkiolp4 4mo agoI think the whole post is AI generated. The author could have given a draft as input and perhaps edited the output in a few places. Take this paragraph as example: > Go got generics in 1.18, and they’re useful, but the implementation has constraints (no methods with type parameters, GC shape stenciling, occasional surprising performance characteristics). Rust generics monomorphize, each instantiation produces specialized code with zero runtime cost. Combined with traits, this gives you real zero-cost abstractions. Every sentence says something. Every sentence is important and holds its weight. I would expect that kind of writing from very specialized books or papers, not from a blog post. Also, it makes the post harder (and more boring) to read.
- 0xfurai 4mo agoThe "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.
- deleted 4mo ago[deleted]
- amelius 4mo agoGo has shorter and more predictable GC pauses. If a reference count drops to zero in Rust, it may take an unbounded time to free all the things it refers to (recursively if necessary).
- deleted 4mo ago[deleted]
- cube00 4mo agoI still prefer having deterministic control over when the free occurs. For example, I can transmit the response to the client and then free the memory afterwards so they're not kept waiting.
- cbondurant 4mo agoI already use Rust and don't have experience with Go, so this article maybe isn't super for me. I do have one nitpick though: Stating that data races are "caught at compile time" in Rust feels like it is overstating the case, at least a little. It sounds a bit like its implying Rust can also handle things like mutual lock starvation, or other concurrency issues. When that's simply not the case. I know "data race" is technically a formal term, with a decently narrow scope, yet I still think it could be a bit clearer about it.
- tptacek 4mo agoThis 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.
- com2kid 4mo agoUs 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.
- satvikpendem 4mo agoCheck out Perry the TypeScript compiler to native code
- tptacek 4mo agoI 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!
- 4mo ago
- wpollock 4mo agoVery nice write up! I am a fan of Rust and have little exposure to Go. That said, a couple of very minor points: cargo audit is not built-in, it is 3rd party. (The comparison table near the top isn't clear about that, and the following text stating more is built-in for Rust than for Go might be confusing. I would suggest adding an asterisk to mark built-ins in that table.) cargo watch has been in "maintenance mode" for some time. The author of that suggests cargo bacon instead.
- hasyimibhar 4mo agoIt is also easier to make your code deterministic with Rust vs with Go, which is incredibly useful if you need to perform deterministic simulation testing + property-based testing. I recently wrote a Postgres-to-Iceberg data mirroring tool [1] in Go, but I ported it to Rust because I wanted the ability perform DST without fighting Go's runtime [2]. But if the domain is not critical that warrants DST, I would still pick Go over Rust any day. [1] https://github.com/polynya-dev/pg2iceberg https://github.com/polynya-dev/pg2iceberg [2] https://www.polarsignals.com/blog/posts/2024/05/28/mostly-dst-in-go https://www.polarsignals.com/blog/posts/2024/05/28/mostly-ds...
- LoganDark 4mo agoI still think rustfmt made a mistake by going with four spaces. It's basically inferior for everything except forcing everyone to use the same indentation width, which is actually a downside, since I constantly encounter two-space indent codebases that I can't read and also can't change to four spaces because it's not tabs. Also translating spaces to tabs visually is undecidable thanks to alignment, while the inverse is not true. Ugh.
- cyann 4mo agoI've got a `.rustfmt.toml` file in all my repos with hard_tabs = true
- LoganDark 4mo agoYep, but because it's not the default, plenty of ecosystem tooling just does not properly track the two separate types of leading whitespace (indentation vs alignment) and will happily conflate every tab_width characters of alignment with an indentation level (which is grossly incorrect). I don't have an example off the top of my head because I run very far each time it happens.
- dilyevsky 4mo ago> Under heavy allocation, P99 latency tails are noticeably worse than a Rust equivalent that simply doesn’t allocate on the hot path. Lmao so not an equivalent then? Standard glibc malloc, which is default in rust, will also similarly degrade albeit for different reasons.
- h4kunamata 4mo agoRead migrating from one hype to another, developers never learn or change, do they?? It feels like yesterday when every single project was moving to Go just because it was the new hype, that was until Rust was born. We are already seeing projects dumping migration to Rust because the grass is not always greener on the other side. We will be seeing this again, "Migrating from Rust to XYZ"
- zjy71055 4mo agoI was a Go engineer for years and have shipped a lot of Go. I never properly learned Rust. Over the past year I've been using AI to write small Rust tools for myself — I barely read the code, and honestly it just works. But for serious projects I expect to maintain long-term, I still pick Go. Today I want code I can actually own and reason about myself. Give it a year or two and I probably won't be writing code by hand at all. Once the AI owns the code anyway, that reason disappears — and at that point Rust's guarantees win. So I suspect I'll end up leaning Rust.
- euroderf 4mo ago> But for serious projects I expect to maintain long-term, I still pick Go. Maintenance is a big win for Go imho - that you can go to code you wrote a year or more ago - and jump right back into it, with little-to-no re-learning curve. The syntax is not providing cover for complexity bombs, and the tools keep the workflow simple and quick. How is it with Rust ? Does one's own old code remain maintainable ?
- hebetude 4mo agoNot sure the article is … accurate? Go has a large standard library. Rust leans on third party cargo libraries which fall into the supply chain attack and has a small standard library. Anyways, that feels immediately biased in the article. Also 11% use Rust? I don’t see that penetration in real long term products. Sure lots of tui apps these days but not things that you can make money working on.
- whilenot-dev 4mo ago> Also 11% use Rust? These percentages are from the JetBrains State of Developer Ecosystem Report 2024 on the question "Which programming languages have you used in the last 12 months?"[0]. I think a better datapoint would be the "Primary Programming Languages" in the 2025 report[1] where Rust sits at 4% and Go at 8%. [0]: https://www.jetbrains.com/lp/devecosystem-2024/#KeDHWJ https://www.jetbrains.com/lp/devecosystem-2024/#KeDHWJ [1]: https://devecosystem-2025.jetbrains.com/tools-and-trends https://devecosystem-2025.jetbrains.com/tools-and-trends
- netheril96 4mo agoI've swinged between Go and Rust for my personal projects multiple times. For work, it is decided by the management so not my problem. The biggest gripe I have with Go is the lack of *any* compile time check for mutex. Even C++ has extensions like ABSL_GUARDED_BY. For a language so proud on concurrency, it is strange not to have any guardrails.
- ted_dunning 4mo agoThe guardrails are channels. If you have a mutex on a structure, linters such as are packaged into Goland will catch oversights quite effectively. If you are using fancier concurrency structures, you should consider channels instead.
- netheril96 4mo agoChannels are not for everything. Plenty of mutex cases cannot be rewritten as channels, or will be very unwieldy so. In fact, every large Go project I have seen uses mutex here or there.
- kune 4mo agoTheoretically you can use channels to simulate a mutex, but I agree with you there are use cases where a mutex makes more sense. They are even used in the standard library, for instance to implement sync.Once. But generally I would agree that if you need to code parallel execution, channels are a good way to do it, because you can avoid race conditions if you share data only over channels. The biggest problem is that a lot of people don't understand, that channels with a buffer larger than 1 are a sign of problems in the architecture. There is a type of parallel programming with workers for specific functions, that always leads to performance issues. The problem is you need to right-guess the distribution of work, when you have to define the amount of workers for a specific function. At least one go routine for one request is a much better approach than function-specific workers.
- nirui 4mo ago> It confuses easiness with simplicity A lot of libs/packages in Go's stdlib also has this problem. They like to package everything in a very tight interface (very obvious example includes crypto/* and http), without exposing implementation detail to the end user. Doing this of course has it's benefits, but if the feature provided by the stdlib slightly don't fit you needs, then you might have to write your own (potentially unsafe and/or less performant) one from zero. Rust is great overall, but there's some oddities. For example their lib.rs / `mod` is very, very unintuitive, it felt overdesigned and unnecessarily complex (just see [their book]). I like what Go or Java did to their lib/package systems, it's much better that way. [their book]: https://doc.rust-lang.org/stable/book/ch07-05-separating-modules-into-different-files.html#alternate-file-paths https://doc.rust-lang.org/stable/book/ch07-05-separating-mod...
- magicalhippo 4mo agoI've come to hate hiding internals. Put them in a namespace which makes it clear there's no API stability guarantees, but make them available if needed. As you note it's just pain with no gain to properly hide them. Users can't readily work around bugs or extend functionality.
- nirui 4mo agoSometimes hiding internals is reasonable, but it could cause inconvenient. Exposing everything could make it harder to do interface management etc. It's really a system design problem rather than access control: if you separate functional modules in a reasonable way, then it can be better reused.
- magicalhippo 4mo agoOnly if you use a backwards language with non-existing namespaces. I don't see how it changes anything if you have namespaces. After all, private/protected/public are just namespaces, they are just implicit rather than explicit.
- shevy-java 4mo agoSome years ago Go was all the hype rage. Now Rust is the new Go. I find that very confusing.
- p2detar 4mo agoSome folks already dropped rust and went with zig. Honestly, to me it seems only devs at the peak density of the programming bell curve, are the ones arguing about “the better” programming language.
- deleted 4mo ago[deleted]
- fithisux 4mo agoJVM languages to Rust, I understand it somehow. But Go to Rust??? It does not make any sense.
- hu3 4mo agoThey run a Rust consultancy business. Anything is worth converting to Rust, for the right price.
- denysvitali 4mo agoThe article seems to be just a way to say "Rust is better" - and it fails to do so by spreading misinformation such as the channels part (https://corrode.dev/learn/migration-guides/go-to-rust/#channels https://corrode.dev/learn/migration-guides/go-to-rust/#chann...) or making a fair comparison of pprof vs Rust's flamegraph. It also skips entirely over debugging (delve vs gdb), IDE support, ecosystem (why the hell does Rust have N async runtimes?!), statically linking and so on. A comparison between the performance of RLS / rust-analyzer (painfully slow) and gopls would be enough to kill the whole argument about developer happiness and productivity. It even passes traits as a "reason to switch" to Rust - where in fact it would probably be a reason (IMHO) not to use it (together with lifetimes). I think both languages are amazing, so a migration Go -> Rust (or Rust -> Go) makes no sense most of the time. I've written code in both for a while now, so I know the pain and advantages of both. For example, Go sucks at microcontroller stuff - in fact it's not even Go officially (see my presentation about porting "Go" to an ESP32-S3 [1]) - whereas Rust is amazing and even has a strong project behind (https://esp.rs https://esp.rs) and amazing tooling (probe-rs & co). What's also not addressed here is the Go ecosystem. The Go packages are one `go mod add` away (pkgs.go.dev) and the module owner guarantees v1 backwards compatibility for the whole lifetime of the module. This means that, no matter what happens, your dependencies will always be up-to-date with no migration struggle. This makes creating stuff for anything around the Kubernets ecosystem a breeze, you can literally import the types from another project and start your integration right away. The most valuable part of the article seems the link to the opposite view (https://blainsmith.com/articles/just-fucking-use-go/ https://blainsmith.com/articles/just-fucking-use-go/). They're equally biased, but one is more straightforward than the other. All in all, it's not a fair comparison and it's very biased (which is fair) - at the same time I think the idea behind the article is "wrong". If you find yourself migrating from Go to Rust (or vice versa), you're likely doing something wrong - and the performance gain is not the reason you're really doing it for. [1]: https://docs.google.com/presentation/d/18jWccV-F2FguZiB5gXLkQFAhUFK_yl7FwkgtldwstxI/edit?usp=drivesdk https://docs.google.com/presentation/d/18jWccV-F2FguZiB5gXLk...
- up2isomorphism 4mo agoI never feel rust learning curve is steep. It is just everything is awkward, even more awkward than modern C++.
- xuzhenpeng 4mo ago[flagged]
- danborn26 4mo agoGreat writeup. The section on error handling differences is spot on, especially how Rust's Result type changes the way you structure application flow.
- Luker88 4mo agoI write purely Go at $dayjob, but I write purely Rust in my projects. I have a huge list of things that I have in Rust that I would like in Go, but I don't have a single thing I am missing from Go in Rust. I grow tired of golang "dumb it down" approach as I find it actually just shifts more and more work onto me. Is anyone in a different position? What does Go have that rust does not?
- wanderlust123 4mo agoThe simplicity of Go is a feature…
- Luker88 4mo agoI have to come to believe that Go is simple for the compiler, not necessarily for the programmer. `nil` is not simpler than references and Option<T>. lack of enum is complicating my code. automatic type promotion is a hidden bug waiting to happen and preventing proper strong types, lack of `?` is making things verbose. struct tags look simple, until you realize they are hiding a ton of code and creating a ton of corner cases that you still have to manually check, and are completely nonstandard (hello json and `default`, `omitempty/omitzero` etc...). `nil` and interfaces? it took decades to recognize that Generics simplify things for the programmer, no Send/Sync like in rust makes concurrent code more error prone, etc, etc... And that is without talking about the standard library, where "simple" somehow becomes having `url.Parse` that accepts everything without errors. http body `nil` vs `NoBody`. Who hasn't had to write the Nth implementation of a pipe between reader and writer? Apparently most libraries hear "simple" and think "dumb". We could go on for hours. Golang is much easier to learn, and rust does remain much more complicated. I don't thing golang hit his target of "simplicity" honestly.
- runtime_terror 4mo ago> I have to come to believe that Go is simple for the compiler, not necessarily for the programmer. You're welcome to believe whatever you want but Go is pretty universally known as one of the simpler, easier to learn compiler languages in existence.
- DeathArrow 4mo agoTLDR: >The other prior worth disclosing: I run a Rust consultancy; of course I’m biased!
- DeathArrow 4mo ago>Go developers don’t usually come to Rust because Go is “too slow.” For most backend workloads, Go is plenty fast. People are generally a bit frustrated with Go’s verbose error handling, the danger of segmentation faults from nil pointers, and the lack of generics (for a long time) or any sophisticated type system features, such as enums or traits. Interfaces are not a worthy replacement for traits, and the Go standard library has some weird gaps, such as the lack of a Set type. (The idiomatic workaround is map[T]struct{}, which works fine in practice but is a tell that the type system isn’t quite carrying its weight.) If those are issues, I rather use C#/.NET than expose both developers and AI agents to a cognitive overload. However, those are not big issues to me, and at least in the present day, Go seems to excel at the things it is supposed to: backend and microservices. Sure, you can find some small issues with Go if you are really nitpicking, but you can find bigger issues with other languages. Sure, Go is boring as f..k, but I don't care and the agents don't mind, they love Go. Most people prefer reading Go than reading Rust. Go allows a fast way to production and for many startups and small companies, that matters a lot. I don't hate Rust, and even use it - for where I think it makes sense, but for backend and microservices, Go seems a better fit. As always, this is an opinion, derived from my personal experience, take it with a grain of salt, your experience might be different.
- sgt 4mo agoMeanwhile.. Java's still around. Modern, and fits the LLM paradigm quite well. It's not going to be as amazing or fast as Rust is, but close.
- p2detar 4mo ago> as amazing or fast as Rust For cli tools, game engines, etc. certainly so. But what about monoliths? Do we have enough data to say Rust handles long-running monolith apps exposing web and other network services better than the JVM with its hot spot? I haven’t come to any stats on that matter, yet.
- pas 4mo agoIf you can encode your request processing patterns in statically sized types, then you can get the same high-level memory allocation behavior on both platforms. Arguably Rust makes this a bit easier. (Though I have no idea how much of the concepts of mechanical sympathy made it to mainstream Java.) If you have some kind of super vague complicated patchwork of plugins that all contribute to processing, then the JVM seems to be the more convenient choice. https://martinfowler.com/articles/mechanical-sympathy-principles.html https://martinfowler.com/articles/mechanical-sympathy-princi...
- MeetingsBrowser 4mo agoIndirect evidence, but parts of AWS and cloudflare have been running Rust in production for close to a decade now and neither company looks to be itching to move services back to Java.
- nicce 4mo ago> other network services better than the JVM with its hot spot? JVM hotspot optimization is just band-aid for something Rust does always everywhere naturally? Assuming that you use lifetimes etc properly and not going to Arc rampage.
- za3faran 4mo agoRust: concat/string time: [77.801 ns 78.103 ns 78.430 ns] change: [+0.0275% +0.3169% +0.6169%] (p = 0.03 < 0.05) Change within noise threshold. formatted/string time: [31.471 ns 31.569 ns 31.699 ns] change: [+0.1277% +0.3915% +0.6788%] (p = 0.01 < 0.05). Change within noise threshold. Java Benchmarks.concat string avgt 15 8.632 ± 0.105 ns/op Benchmarks.format string avgt 15 64.971 ± 1.406 ns/op Java's string concat is faster than rust's offerings.
- HackerThemAll 4mo agoThe datetime to string conversions in Go are devil's spawn.
- kermatt 4mo agoShare some examples?
- HackerThemAll 4mo agoThe template string "2006-01-02 15:04:05.999999999 -0700 MST" says it all. It's a really bad joke or an excellent trolling. The entire world have used: %Y for the year. %m for the month. %d for the day. %H for the hour. %M for the minute. %S for the second. for over 50 years, but Golang forces me to remember "06" for a year, "15" for an hour and "05" for second. and "MST", the Mountain View time, that particular time zone moniker, in a center of the universe, as a placeholder for a real time zone. Yes, the Mountain View, not UTC ("Z"ulu time) like a sane person would do (although nobody sane would implement that format).
- embirdating 4mo ago[dead]
- asplake 4mo agoI
- 3uler 4mo agoGolang is an amazing runtime with a bad language, one that conflates simple with easy. I view it the same way I view Java: a fine choice for a corporation, but nothing to love. Although Java’s gotten a lot better lately.
- DeathArrow 4mo agoFor me having the proper tool for the job trumps loving. I don't have to love the language, I have to love the process and the end result.
- virtualritz 4mo agoI would add that Rust also has naming guidelines and sticking to them removes or at least minimizes the occurrence of another common topic of discussions on PRs/reviews. In the article, if you were to mention & follow them GetUser() in Go becomes user() in Rust[1], not get_user(). [1] https://rust-lang.github.io/api-guidelines/naming.html#getter-names-follow-rust-convention-c-getter https://rust-lang.github.io/api-guidelines/naming.html#gette...
- deleted 4mo ago[deleted]
- bnolsen 4mo agoI would think that you might have a better time going from go to zig. You would have to provide a pattern for implementing the interface model go uses.
- MeetingsBrowser 4mo agoWhat are the benefits of moving from Go to Zig? It seems like you lose a lot (automatic memory safety, simple language, easy concurrency) and gain very little.
- sylware 4mo agoWhat about AI assisted migration? There was a signal to assist c++ to plain and simple C AI mass migration. Removing any languages with ultra-complex syntax towards simple and plain C is always a good thing.
- tuptup 4mo ago[dead]
- apatheticonion 4mo agoI wrote Go professionally for years. Moved to Rust and couldn't be happier. There are some annoying syntax quirks but they are minor. After writing web services, GUI apps and terminal apps professionally in Rust, I honestly struggle to see a use case for other languages.
- apatheticonion 4mo agoShameless plug. I've been developing a web server library for Rust based on the ergonomics of the Golang standard library. It has a router, middleware, and uses AsyncRead, AsyncWrite for the request/responses. I use this for my production applications and have found it much easier to work with than Hyper or Axium. https://github.com/alshdavid-public/uhttp/blob/main/examples/counter_app/src/main.rs https://github.com/alshdavid-public/uhttp/blob/main/examples... The API is largely complete but under the hood I have a few things that need doing. Open to contributions so please feel free to help out
- drykiss 4mo agoQuite new to Go, so sorry in advance for a stupid question: > "Go got generics in 1.18 (March 2022), thirteen years after the language shipped. They are useful, but they feel tacked on, and in practice they have most of the downsides of a generic type system without delivering the upsides you’d expect coming from Rust, Haskell, or even modern C++." The problems with Go generics have now largely been solved, haven't they? Is this comment from the author still applicable?
- aatd86 4mo agoThat's the thing, a programming language is not something static, it evolves. For instance, people are working on adding generic methods for the next release cycles. And what the article complains about is by design, not a bug. It is a tradeoff made to avoid bloat. In any case, given the future possibilities, I'd bet on Go. If anything, the language is just slower to evolve because every language change means the tooling needs to catch up. And now llms would have to catch up. ChatGPT is still using Go 1.23 for instance...
- yamapikarya 4mo agoi like go because it's simple and just works. i like the error handling, if err != nil return err, i like the philosophy to focus using stdlib instead choose which libraries are the best for doing x. i like how go handle the concurrency like using channel or sync.waitgroup. i am very biased but someday i will also learn rust
- jafffsuds 4mo ago> There’s no built-in goroutine-style preemption. Long CPU-bound work in an async task starves the executor; you offload to tokio::task::spawn_blocking or rayon instead. I don't know why anyone uses spawn_blocking for CPU-bound tasks. It's clearly designed for blocking IO tasks. There's a reason why Erlang cordons them separately into Dirty CPU and Dirty IO schedulers.
- JodieBenitez 4mo agoI'll stick to this advice: https://kerkour.com/rust-backend-services-problems https://kerkour.com/rust-backend-services-problems
- phplovesong 4mo agoGo has warts, but projects like Lisette (https://lisette.run/ https://lisette.run/) try to fix those. Go has bare syntax, as lack some (modern?) features. But imho it has a superb runtime, eg has a WAY better concurrency story than what you see in Rust.
- rr808 4mo agoOne reason I like Go is the fast compile. Rust really slows you down. Esp in days of AI when agents are building/testing in cycles.
- chlorion 4mo agoHow large are your rust projects? I am able to write rust on a moto g power (a cheap android smartphone) inside of termux, running on battery, in battery saver mode, and cached compile times for every single one of my projects is under 5s easily, if not faster. Fast enough that I don't notice it at all. Even a "cold" compile was under 1 minute for me, and I have a decent amount of deps. I guess my projects are fairly small compared to others though so idk.
- deleted 4mo ago[deleted]
- mxey 4mo ago> You literally cannot dereference an Option without acknowledging the None case. Whole categories of pager-duty incidents disappear. This is at the very least misleading, given that you can use unwrap. Regarding error handling: will a parser error in the config return an error that includes the name of the file that’s failed to parse? That’s the kind of useful context that I add to errors in Go.
- tuetuopay 4mo agoThe difference is, unwrap will stick out like a sore thumb, and it’s opt-in. You explicitly tell "this may panic". As for error handling, this kind of enrichment is usually left to the caller (that is, the end application), with error libraries like anyhow where you can add arbitrary string contexts to an error. You would end up writing `Config::load(path).with_context(|| format!("Failed to load configuration file {path}"))?`.
- seabrookmx 4mo agoWhile I agree it's better than the golang alternative, it's definitely still a footgun. See Cloudflare's Nov 2025 outage.
- LucasOe 4mo agoCalling unwarp is acknowledgement
- AtNightWeCode 4mo agoAnybody who actually moved a set of services from Go to Rust? I've heard that in practice Rust uses more memory than Go for web services. When I ask LLMs I get the same answer as in the article. A 30-50% reduction but then also claims on how much memory Go uses. Which is about 5-10x more than our average service use.
- kakuremi 4mo ago[flagged]
- sg1apm 4mo agoCurious about the operational side: did the migration affect your deployment pipeline complexity significantly? We recently rewrote a monitoring dashboard from Python/Qt to Go specifically to get a self-contained binary with no runtime dependencies — the deployment story for Go is hard to beat for internal tooling even if Rust would win on performance.
- cliftonk 4mo agoI have preferred rust for many years now, but we’ll be using models spitting out 500-1500 or more tokens/sec soon and rust compile times are glacially slow (while go is almost instantaneous).
- sspoisk 4mo ago[flagged]
- Surac 4mo agoJust on Question: Why? Why migrate and open a new can of worms?
- jurschreuder 4mo agoI'm moving more and more from Python and Golang to C++. C++ also forms a natural barrier to entry.
- nathanmills 4mo agoYou are Evil.
- booleandilemma 4mo agoRust is not a good language for web development and I'm convinced that the majority of developers who push it for web development are just trying to show off.
- anonyfox 4mo agowith web framewworks like actix or rocket itsd actually not much different to python flask or nodejs express or .... . but i am a cheap person and prefer to cram as much stuff onto my $4 DO droplets as possible, and rust brings you very far here. might be not a concern for funded startups or big enterprises, but deploying small/mid projects to essentially minimal hardware really makes my wallet happy, plus I essentially never ever had to fix runtime issues, at all, for years. and this was before LLMs were a thing, so handwritten Rust in a fullstack way, at times even WASM frontend SPAs that still kinda just work.
- sov 4mo agothe whole article kinda reads like "i have a leak in the basement of my house in the pacific northwest. the solution? im moving to nevada" i dont dislike rust at all (infact, its rustler interop with elixir/erlang is great), but the article reframing a bunch of intentionl design choices (that i would broadly argue as good design choices) in golang as shortcomings is so weird (gc, generics, error handling, etc.). especially so when they're framed in such a way to make error-prone go seem inevitable, or are directly comparing well-written rust and poorly-written go. take, for example, the section on data races. the article broadly classifies rust as data race free and golang as full of synchronization issues. and this is true if you only actually care about data races (not race conditions broadly), assume all of your rust is safe rust, and none of your golang uses any of the available solutions (atomics, synchronization primitives, channels, etc.) to data races. yes, go leaves much of the behaviour up to the programmer. this isn't a downside. more egregiously, the article glosses over two of the biggest and, to me, most critical differences between the two language. first, go compiles FAST. i can write something and test it immediately, including stepping through the code. i dont need to context switch away from the task and can easily, and quickly, program fixes and changes and features. this is such a huge development gain that switching away from it would require an incredibly good reason. secondly, the package structure of rust offers a clear vector for supply-chain attacks. not that golang is perfect in that sense, but it has a ton of factors that reduce the likelihood, and if i'm being really picky about safety it's going to be a big consideration.
- anonyfox 4mo agoI use both languages and in spirit you are right, btu in my experience its more nuanced. first of all the way inline unittests in the same file is a way to have very fast cycle times in TDD too in many situations, still slower than go full compile yet much less painful than full recompile in rust. second, you typically need way less debugging cycles in rust to begin with. so its more like slower but fewer cycles.