I keep reaching for Go. Not because it’s trendy or because someone told me it’s the best language—but because every time I come back to it after months in another stack, I feel like I can breathe again.
TL;DR
Go’s stability and simplicity keep me coming back. The compatibility promise is real, the release cadence is predictable, and the language favors a small set of composable ideas over clever magic. The posts below cover recent releases and—new—a supply chain angle: what Go does not do at go get time, what still bites at build and runtime, and how I pair that with the npm side of polyglot repos.
Stability that respects your time
Go has a compatibility promise, and they actually mean it. Code I wrote years ago compiles today without touching a line. The six-month release cadence is clockwork, and upgrades are boring in the best possible way: run the tests, read the release notes, ship it.
Compare that to ecosystems where a major version bump means a week of dependency archaeology. Go respects your time. When I upgrade, I’m not gambling—I’m applying a known diff. I’ve written about the specifics in my Go 1.25, Go 1.26, and Go 1.27 posts.
That sounds small until you’re maintaining four services and a CLI tool and you just want things to keep working.
Simple, not easy
This is the distinction that matters most to me. Go isn’t “easy” in the way that hides complexity behind magic. It’s simple—a deliberately small set of ideas used everywhere:
- Goroutines and channels for concurrency
- Interfaces for abstraction (no inheritance trees)
- Structs and methods for data and behavior
- Errors as values, not exceptions
That’s mostly it. You learn these once, and then you can read any Go codebase. The patterns repeat. The surprises are rare. When something breaks, you can trace it without a PhD in framework internals.
I’ve worked with languages that offer clever shortcuts and abstractions that feel great on day one and terrible on day ninety. Go’s trade-off is the opposite: a little more typing up front, a lot less head-scratching later. I’ll take that deal every time.
Supply chain: not the same problem as npm
Go modules do not run arbitrary install hooks for dependencies the way JavaScript package managers often do; most of the risk shifts to imports and init, go generate, cgo, and whatever else runs on the same laptop or CI job (including front-end installs). I wrote Supply chain attacks and how to stay safe with Go as the Go half of a diptych with Mini Shai-Hulud and hardening npm, pnpm, and Bun—worth reading if you share runners, tokens, or monorepos across stacks.
Posts in this series
- Database-Compatible Structs in Go — How
database/sqlconverts fields and when custom types needScannerandValuer. - Go 1.27 Release Notes — Generic methods and UUIDs, plus the graduation of JSON v2 and goroutine leak profiling.
- Supply chain attacks and how to stay safe with Go —
init,go generate, cgo,govulncheck, vendoring, and why npm worms still matter to Go teams. - Go 1.26 Release — Performance wins, stronger security defaults, and the revamped
go fix. - Go 1.25 Deep Dive — Green Tea GC experiment, JSON v2, and the tooling overhaul.