Why Go?
TypeScript pays the bills. Go keeps me curious.
Day to day, Node.js keeps the lights on. Nest.js gives it structure, polish, and sanity. The ecosystem’s massive, the tooling solid — everything you’d expect from a mature stack.
But when I’m building something for myself? I keep choosing Go.
It took me a while to figure out why.
The Thing About TypeScript
TypeScript solved real problems. Type safety in JavaScript was a revolution. I remember the before times, runtime errors that should’ve been compile-time, refactors powered by grep, and the constant uncertainty of what a function actually returned.
But here’s what nobody talks about: TypeScript is a bandaid on JavaScript. A brilliant bandaid, but still a bandaid. Every new feature adds another layer trying to make JavaScript something it isn’t. Generics that vanish at runtime. Decorators still “experimental” after years. Async/await wrapping promises wrapping callbacks. Enums we’re eventually told to avoid.
It’s not bad. It’s just complicated in ways it doesn’t have to be.
When I Found Go
I picked up “The Go Programming Language” fully expecting to hate it. Everyone said it was too simple, too opinionated, missing the “essentials.”
Then I spent a weekend building an API — and something clicked.
The language got out of my way. No Webpack gymnastics. No tsconfig.json. No Babel. No fighting with CJS vs ESM. Just code that compiled to a binary and ran with a single command. Fast.
Later, Rob Pike’s talks made it all make sense — especially Simplicity is Complicated, the idea that constraints can be freeing. Go doesn’t have inheritance because inheritance causes more problems than it solves. It has generics now, but you rarely need them; interfaces and concrete types are usually clearer.
The standard library gives you what you need without the framework churn.
“Go doesn’t have type hierarchy because hierarchies are brittle. Composition is more flexible.” — Rob Pike (Google I/O 2012)
What I Actually Like
Goroutines make concurrency feel natural. Not easy, concurrency is never easy, but natural. No callback hell. No async/await acrobatics. CSP got it right decades ago, and Go actually implements it.
Error handling is verbose, but I’ve grown to prefer it. if err != nil everywhere means I always know where things can fail, and what happens when they do. No exceptions bubbling up from somewhere deep in a library. No unhandled promises waking me up at 2 a.m.
Compilation speed matters more than I ever realised. My Go projects build in seconds. The binary’s self-contained, small enough, and just runs. No node_modules. No containers unless I actually need them. No worrying about Node versions or navigating the package-manager hellscape.
The Honest Part
I’m not ditching TypeScript. I can’t. Too much of the professional world runs on it. Nest.js is genuinely good at what it does. React isn’t going anywhere. I’m not fighting that fight.
But when I’m prototyping something, building tools for myself, or just want to think about the problem instead of the build pipeline. Go wins every time.
It’s not about one language being “better”. It’s about what keeps me focused on solving problems instead of wrestling with tooling.
For me, that’s Go.
If You’re Curious
- The Go Programming Language (Donovan & Kernighan) - Actually worth reading cover to cover
- Effective Go - Free, official, teaches you to write idiomatic code
- Rob Pike’s Concurrency is Not Parallelism - ~30 minutes that’ll change how you think about systems
You don’t need a 10-hour YouTube course. Read the docs. Build something real. See if it clicks.