— notes
Go Was Never Bad
Every time I see that GitHub repo go-is-not-good making the rounds again, I laugh. It’s always shared by people who mistake language cleverness for engineering.
Let me say this clearly: Go is not for everything. It was never meant to be. But if you’re building cloud-native systems, if you’re working with distributed architecture, if you’re running services in production that actually matter – Go is brutal, minimal, and effective.
graph LR
A["No generics"] -- "Go 1.18" --> B["Resolved"]
C["No modules"] -- "Go 1.11" --> D["Resolved"]
E["Error handling"] --> F["By Design"]
G["Concurrency"] --> H["Same as every lang"]Generics
Go 1.18 brought generics. Not the “look how clever I am” kind. The real-world, clean, no-BS kind. I’ve built production-grade code with generics in Go, and it’s boring in the best possible way.
Error Handling
I respect Go’s approach to error handling. It makes you look at your failure paths. There’s no magic trapdoor. You deal with errors explicitly, predictably, and with clarity. Now with errors.Is, errors.As, and errors.Join, it’s not even painful.
Go does not babysit your Concurrency
Go gives you the raw tools to build concurrent systems. It assumes the person writing the code knows what they’re doing. I respect that.
Performance
I’ve deployed Go services that boot in under 50ms and run for months without a hiccup. It doesn’t brag. It just works.
graph LR
A["Go"] --> B["Ship fast, simple"]
C["Java / Spring"] --> D["Medium complexity"]
E["Rust / Haskell"] --> F["Complex, more guarantees"]Personal take
I’ve built banking systems, transaction processors, and cloud-native APIs with Go. It’s not flashy. But Go keeps things simple and predictable, and that’s exactly what backend engineering demands.