Open this lesson in your favourite AI. It'll walk you through the why, explain the demo, and quiz you on the try-it list.
Go has a culture of automated tooling that nobody fights about. gofmt formats your code one canonical way (no Prettier debates, no Black-vs-Blue forks). go vet catches a small set of high-confidence bugs the compiler refuses to (suspicious printf args, unreachable code, lock copying). goimports adds and removes imports. These three run in every Go shop's pre-commit hook and CI gate. Resisting them marks you as new — embrace them and your diffs stay clean.
go fmt enforces Go's canonical whitespace and brace style — unlike most languages, style is not a team choice in Go, it's a compiler-adjacent tool that everyone runs. go vet is a static analyzer that catches real bugs the compiler misses: mismatched Printf format strings, unreachable code, suspicious mutex copies, and more. goimports does what go fmt does, but also manages your import block — adding missing imports, removing unused ones, and grouping them into stdlib vs third-party sections. Running these three before every commit means every diff your teammates review is already formatted and free of a class of common bugs.
gofmt -d . (-d shows the diff without writing). On a fresh codebase it should output nothing — that's the whole point.fmt.Printf("%d", "abc") — and run go vet ./.... See exactly what it catches.goimports and configure your editor to run it on save. Now you never type imports by hand again.gofmt and go vet checks to a pre-commit hook (or CI). It's 4 lines of shell and saves hours.Use these three in order. Each builds on the one before.
In one paragraph, explain why the Go community standardized on `gofmt` instead of leaving formatting to taste — and what the cultural payoff has been.
What does `go vet` check that the Go compiler doesn't, and why are those checks not promoted to compile errors? Pick one (e.g. printf args) and explain the design tradeoff.
When does a project graduate from `go vet` to `staticcheck` or `golangci-lint`? Compare the three and recommend a setup for a production service.
# format every Go file in the module (rewrites in place):
$ gofmt -w .
# go vet — static analysis on top of the compiler:
$ go vet ./...
# typical finding:
# ./main.go:8:2: Printf format %d has arg "x" of wrong type string
# goimports = gofmt + auto-add/remove imports:
$ go install golang.org/x/tools/cmd/goimports@latest
$ goimports -w .
# wire all three into your editor on save (gopls handles fmt + imports;
# vet runs on the diff in CI). pre-commit hook example:
$ cat .git/hooks/pre-commit
#!/bin/sh
gofmt -l . | tee /dev/stderr | (! read)
go vet ./...go run main.go