Skip to content
Tech News
← Back to articles

A Gopher Meets a Crab

read original more articles
Why This Matters

This article highlights the practical advantages of Rust over Go, especially in areas like exhaustive enums and error handling, which can lead to more reliable and maintainable code. For developers and the industry, embracing Rust's features can improve software robustness and reduce bugs, making it a compelling choice for modern system development.

Key Takeaways

I’ve been writing Go for about a decade, and for most of that time Rust has been the language I respected from a polite distance. I bought the book, thumbed through it, but mostly it sat on the shelf. I gave rustlings a try once or twice but always ended up wandering away. I never had the hook to really motivate me to dig in. Miren is at the inaugural TokioConf this week (I’m writing this from the plane there), and my desire to cook up a decent demo presented the perfect opportunity.

So I built a chat server. Well, okay, I told Claude to build a chat server, and then spent a long time asking Claude about what the heck it just wrote. Treated it like my Rustacean pair I could bug to explain things to me. Not nearly as good as a human, but patient, and available over airplane wifi. It’s in our repo full of sample apps, running live at chat.miren.toys. Swing by this week and you might find a few friendly strangers already typing.

Notes from a gopher

So now I’ve spent some honest hours trying to fit Rust into a Go-shaped brain. Here’s what fit nicely and what popped back out the other side.

Exhaustive enums are the thing I’ve wanted in Go for years. In Go, I either reach for codegen or write a test case any time I want to prove I handle every variant of a type. Rust’s compiler just checks. Add another variant tomorrow and every match in the codebase that doesn’t cover the new case lights up red at compile time. I can stop writing tests for my own forgetfulness.

The ? operator is kind of a revelation to an if err != nil -addled brain like mine. One character for what used to be a block. Though I’ll admit, the number of implicit exits from a function still makes me a little itchy. It’s an interesting spot where the two languages diverge on what’s worth making explicit. Go wants you to see every return path, even the sad ones. Rust trusts the type system to carry it instead.

The first line of Rust that made me laugh out loud:

match tokio :: time :: timeout ( Duration :: from_secs ( 2 ), receiver . next ()) .await { Ok ( Some ( Ok ( Message :: Text (t)))) => { /* happy path */ } _ => { /* anything else */ } }

Reads like a nervous little parser muttering to itself. “Ok… some… ok… message… text!” Each layer hoping the next one holds. My reaction to Claude was “do rust-heads not blink at a line like that?” Answer: yes, a little. This is on the border of “clever” and “just write it flat.”

We refactored to lean on ? instead of the big match clause, which gets you to a slightly cleaner helper:

... continue reading