Overview
gofmt prints Go source in the one canonical style — no configuration file, no options to
argue over. "Gofmt's style is no one's favourite, yet gofmt is everyone's favourite": by
removing formatting from the review surface entirely, diffs show only meaning. It is best
understood as a language feature, not a lint.
Key points
- Zero configuration: no line-length knob, no brace-style debate; tabs, and that's the end of the conversation. Every Go codebase on earth is formatted identically.
gofmt -w .rewrites in place;gofmt -llists non-conforming files (the CI check).go fmt ./...is the module-aware wrapper.gofmt -r 'a[b:len(a)] -> a[b:]': pattern-based rewrites — a lightweight refactoring tool using single-lowercase-letter wildcards over expressions.- goimports = gofmt + imports: adds missing and removes unused import statements,
grouping stdlib before third-party; ships in
golang.org/x/tools. In practice you run goimports and get gofmt for free. - Editor-on-save is the convention: nobody formats manually — gopls applies gofmt/goimports on save in every mainstream editor setup, so the topic simply disappears from daily work.
- gofumpt: a stricter superset (extra rules like no empty lines at block starts, shorter octal literals); gofumpt-formatted code is always gofmt-compliant, so adopting it is safe. Supported natively as a gopls formatting backend.
- Format-on-CI, not format-debates-on-PR: a
gofmt -lgate plus on-save formatting makes style review comments extinct — the cultural payoff Java teams buy with checkstyle/spotless configuration.
Examples
gofmt -l ./... # CI: fail if output non-empty
gofmt -r 'interface{} -> any' -w . # mechanical modernization
goimports -w -local github.com/acme ./... # group company imports last
Related
- The Go toolchain — parent catalog; formatting as part of the single-command story.
- gopls — how formatting actually runs, on save, everywhere.
- staticcheck & golangci-lint — where style ends and lint begins.
- Code review — the review noise gofmt deletes by design.