4 ms·
Author here: I wrote this in 2020, have changed jobs twice since. Both jobs involved Go in some capacity, where it's supposed to shine (web services). It has no
by fasterthanlime 4y ago
Author here: I wrote this in 2020, have changed jobs twice since. Both jobs involved Go in some capacity, where it's supposed to shine (web services). It has not been a pleasant experience either - I've lost count of the amount of incidents directly caused by poor error handling, or Go default values.
If folks walk away with only one new thought from this, please let it be that: defaults matter. Go lets you whip something up quickly, but making the result "production-ready" is left as an exercise to the writer. Big companies that have adopted it have developed tons of tooling around it, use all available linters, do code generation, check the disassembly, and regularly pay the engineering cost of just using Go at all.
That's not how most Go code is written though. I'm interested not in what the language lets you do, but what is typical for a language - what is idiomatic, what "everyone ends up doing", because it is encouraged.
Because that's the kind of code I inevitably end up being on-call for, and I'm tired of being woken up because of the same classes of preventable errors, all the time. It doesn't matter that I don't personally write Go anymore: it's unescapable. If it's not internal Go code, it's in a SAAS we pay for: and no matter who writes it, it fails in all the same predictable ways.
Generics will not solve this. It is /neat/ that they found a way to sneak them into the language, but it's not gonna change years of poor design decisions, and it's definitely not gonna change the enormous amount of existing Go code out there, especially as the discourse around them not being the usability+performance win everyone thought they would be keeps unfolding.
As I've mentioned recently on Twitter, what makes everything worse is that you cannot replace Go piecemeal once it has taken hold in a codebase: its FFI story is painful, the only good boundary with Go is a network boundary, and there's often a latency concern there.
Lastly: pointing out that I have been teaching Rust is a lazy and dismissive response to this. For me personally, I have found it to be the least awful option in a bunch of cases. I am yearning for even better languages, ones that tackle the same kind of issues but do it even better. I like to remind everyone that we're not out there cheering for sports team, just discussing our tools.
If you're looking to reduce the whole discourse to "X vs Y", let it be "serde vs crossing your fingers and hoping user input is well-formed". It is one of the better reductions of the problem: it really is "specifying behavior that should be allowed (and rejecting everything else)" vs "manually checking that everything is fine in a thousand tiny steps", which inevitably results in missed combinations because the human brain is not designed to hold graphs that big.
- mynameisash 4y agoThanks for your amazing articles, Amos! > I'm interested not in what the language lets you do, but what is typical for a language This is the crux of the problem. To step away from Go/Rust and pick on another language, one could argue that Python lets you annotate every variable for some linting checks, but that doesn't mean they all are. This leads to horrible time-sinks where someone accidentally adds a comma to the end of a line, turning a scalar into a 1-tuple. I know folks to whom this has happened and who burned a half day trying to track it down. I personally get annoyed by the "Language X gives me the freedom to do Y." I find that I and a lot of my peers often prefer constraints imposed (instead of freedom given) by the language as a way of preventing countless issues at runtime.
- fb03 4y agoDon't fall prey to an ad-hominem argument - I don't think your article negatively hints at any kind of 'this is a Rust fanboy-made praise text' and it saddens me that a genuinely legit article like this needs to have the author defend himself like this. Your points were well explained. Go has several serious warts which, in my own opinion, are showstoppers, and you are comparing it to a language which is somewhat newer and had more time to mature and of course, learn from other designs and their decisions as well. Generics were intentionally left out, for example, because of the fear-mongering claim that "if you have generics your code is going to automatically become the C++'s STL at some point". After many years, the lack of even minimal generics got so bad they figured they'd start to lose share to rising languages like Nim, Rust and even the old grandpa C#, now portable everywhere with the Core stuff. It is very clear how badly bolted and rushed generics were in Go. Rust has its warts as well and the language spec is already starting to become somewhat... large. We need to be careful not to invent C++2.0 right? ;-) Anyways, just wanted to say this to you in hopes it'd lighten the mood and validate that you are in a good path with these articles. It was a very insightful reading for me. Thank you.
- mseepgood 4y ago> Rust has its warts as well and the language spec is already starting to become somewhat... large It doesn't have a spec, so we don't know how gigantic it would be.