The Go stack we would set up today
Go needs less tooling than any other language on this network. Here is the short list that is actually worth installing.
Go's best property as a toolchain is how little of it there is. go build, go test, go vet and gofmt ship with the language and cover more than most ecosystems manage with twenty packages.
Install these four#
golangci-lint#
The one addition everyone should make. It bundles staticcheck, errcheck, errorlint, gosec, contextcheck and dozens more behind one fast command.
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
golangci-lint runThe config we use is in the failure-mode catalogue, and the rules that matter most are the error-handling and context ones.
The race detector (already installed)#
go test -race -count=1 ./...Not optional. Concurrency is where generated Go is weakest and -race is the only thing that finds it reliably. -count=1 disables test caching, which matters when an agent is iterating — a cached pass is not a pass.
goleak#
go get go.uber.org/goleakfunc TestMain(m *testing.M) { goleak.VerifyTestMain(m) }Three lines, and every goroutine leak becomes a test failure instead of a slow memory climb in production.
air or wgo for reload#
Optional, and pleasant. Rebuilds on save so the feedback loop stays under two seconds.
Editor#
VS Code with gopls is free, excellent, and what most Go developers use. The extension is maintained by the Go team.
The GoLand case is the debugger and the profiler integration. If you spend your days in a large Go service, stepping through generated concurrency code beats reading it, every time.
Hosting#
Go's deployment story is its other quiet advantage: a single static binary, no runtime, a FROM scratch container of a few megabytes.
For a Go binary, a plain VPS is often the right answer — there is no runtime to manage, so the operational overhead of a managed platform buys you less than it does for Python or Node.
App Platform is still the least-effort path if you would rather not touch a server, and the $200 credit covers a good while of experimenting.
Honest note
For a small Go service, Fly.io's free tier and Cloud Run's free tier both work well and we earn nothing from either. Start there if you are just deploying something to see it run.
Learning#
The strongest recommendation on this page. Boot.dev's Go track is project-based in a way that survives the agent era — you cannot paste your way through it, because the thing being taught is the reasoning about concurrency and memory.
For the reference-book shelf: Manning's Go titles go deeper on concurrency patterns than any tutorial, and concurrency is exactly where you need depth when reviewing generated code.
What to skip#
- A dependency injection framework. Go does not need one. Constructor functions and explicit wiring in
mainare clearer and are what the ecosystem expects. - A heavyweight web framework.
net/httpplus the 1.22 routing improvements covers most services. Addchiif you want middleware composition. Anything larger is usually a mistake you notice a year later. - An ORM.
sqlcgenerates type-safe Go from your SQL and is a better fit for the language than an ORM is.pgxdirectly if you prefer. - A second linter.
golangci-lintalready runs the ones you were going to add. GOPATHadvice from before 2019. Modules replaced it. If a tutorial mentions$GOPATH/src, it is out of date.
The whole setup#
linters:
enable: [errcheck, errorlint, govet, staticcheck, contextcheck, bodyclose, noctx, gosec]check: lint test
lint:
gofmt -l -w . && golangci-lint run
test:
go test -race -count=1 -timeout 60s ./...That is the entire toolchain. Everything else is preference.
Common questions#
Do I need golangci-lint if I already run go vet?#
Yes — go vet is deliberately conservative and only reports things that are almost certainly bugs. staticcheck and errorlint, both bundled in golangci-lint, catch a much wider set, including the %w wrapping mistake that quietly breaks errors.Is.
Is -race too slow to run every time?#
It roughly doubles test time. Given that it finds the one class of bug Go's compiler cannot, that is a good trade — and if your suite is too slow for it, the suite is the problem.
sqlc, an ORM, or raw SQL?#
sqlc for most projects: you write SQL, it generates typed Go, and there is no query builder to fight. Raw pgx when you need dynamic queries. An ORM only if your team strongly prefers one.
Get the Go agent pack
A battle-tested AGENTS.md, the review checklist, and the failure-mode cheat sheet for Go. One email, then occasional updates when the tooling shifts. No course pitch.
AGENTS.md now — no email needed.
Disclosure: some links on this page are affiliate links. If you buy something through one, we earn a commission at no extra cost to you. We only list tools we would tell a friend to use, and we say so when we have not used something ourselves. This is how the site stays free and ad-light.