go fix Modernizers & go vet Analyzers
go vet catches suspicious code the compiler accepts, and go fix applies automated rewrites - including Go 1.26 modernizers that update legacy patterns to current idioms.
Search across all documentation pages
go vet catches suspicious code the compiler accepts, and go fix applies automated rewrites - including Go 1.26 modernizers that update legacy patterns to current idioms.
Static analysis in Go starts in the stdlib: go vet ships analyzers for common mistakes like misformatted Printf verbs and unreachable code.
go fix runs fixers registered with the same analysis framework, rewriting sources in place when safe.
Go 1.26 expands go fix with modernizers for patterns such as old loop variable capture and deprecated APIs.
Teams layer golangci-lint and staticcheck on top for broader rules, but vet/fix remain the zero-config baseline every module can run.
Quick-reference recipe card - copy-paste ready.
# Run default vet analyzers on all packages
go vet ./...
# Preview modernizer rewrites without writing files
go fix -diff ./...
# Apply modernizers and review in git diff
go fix ./...
# Run a specific analyzer (example: printf)
go vet -printf=false -assign ./...When to reach for this:
go vet ./... in CI on every PR alongside tests.go fix -diff after upgrading Go to see modernizer suggestions before applying.golang.org/x/tools/go/analysis for org-specific rules.// before modernizer: loop variable capture in closure (pre-1.22 style risk)
package worker
func Jobs() []func() int {
ids := []int{1, 2, 3}
var fns []func() int
for _, id := range ids {
fns = append(fns, func() int { return id })
}
return fns
}go vet ./...
go fix -diff ./...
go fix ./...
go test ./...// after go fix modernizer (illustrative - exact rewrite depends on analyzer version)
package worker
func Jobs() []func() int {
ids := []int{1, 2, 3}
var fns []func() int
for _, id := range ids {
id := id // modernizer may insert shadow copy where still needed
fns = append(fns, func() int { return id })
}
return fns
}What this demonstrates:
go vet flags constructs that compile but behave oddly.go fix -diff shows patches before you commit them.go/packages, type-check them, then run analysis passes registered via analysis.Analyzer.go vet reports diagnostics to stderr and exits non-zero when issues exist.go fix runs analyzers that implement SuggestedFix and writes updated source files.go test does.| Analyzer theme | Example issue |
|---|---|
printf | Wrong verb for argument type |
assign | Self-assignment or useless assignment |
unreachable | Code after return/panic |
structtag | Malformed JSON or DB struct tags |
errorsas | errors.As target not pointer to error type |
loopclosure | Loop variable captured by goroutine or defer |
go fix (not a separate binary).git diff - fixers assume common cases, not every domain invariant.# Install extended analyzers (staticcheck) for local runs
go install honnef.co/go/tools/cmd/staticcheck@latest
staticcheck ./...
# golangci-lint aggregates vet, staticcheck, gosec, and more
golangci-lint run ./...go fix without tests - modernizers can change semantics at edge cases. Fix: full go test ./... and targeted benchmarks after every fix pass.go vet itself.analysistest package.vendor/ and generated dirs; fix inputs or templates instead.| Alternative | Use When | Don't Use When |
|---|---|---|
staticcheck | Deeper bug and performance checks | You only need the stdlib baseline |
golangci-lint | One config for dozens of linters | Tiny repos where go vet is enough |
go fix modernizers | Bulk upgrades after Go version bump | Hand-written legacy code with subtle invariants |
| IDE inspections (gopls) | Immediate feedback while typing | CI still needs command-line gates |
go vet ships a small stdlib set focused on definite bugs.
staticcheck adds hundreds of checks maintained by the Go community.
Fixers may format changed regions.
Run gofmt or goimports on the whole tree if style drifts.
Yes.
Use golang.org/x/tools/go/analysis and register it with a driver or custom multichecker.
Linters enable stricter or additional rules.
Treat golangci-lint as a superset, not a replacement for tests.
go fix analyzers bundled with newer Go releases that rewrite outdated patterns to current idioms.
They expand over time; read release notes when upgrading.
Usually no - CI should be read-only.
Run fix locally or in a dedicated bot PR, then commit results.
Refactor if possible.
For exceptions, use //nolint comments only with team policy and a tracked reason.
No for your module if dependencies are cached.
Analyzers only type-check local and module sources.
Yes.
It loads _test.go files the same way go test does.
gopls runs many analyzers in the editor for diagnostics.
go vet and CI linters keep team-wide gates consistent.
go vet exampleStack versions: This page was written for Go 1.26.x (Green Tea GC default, go fix modernizers - verify patch at build), chi (latest - verify at build), gin (latest - verify at build), echo (latest - verify at build), google.golang.org/grpc (latest - verify at build), sigs.k8s.io/controller-runtime (latest - verify at build), kubebuilder (latest - verify at build), tinygo (latest - verify board targets at build), wazero (latest - verify at build), and golangci-lint (latest - verify linter set at build).
Reviewed by Chris St. John·Last updated Jul 19, 2026