Catch Likely Mistakes in Go Code with go vet
You will run Go's built-in static checks against a module, narrow the check to a package when needed, and distinguish a clean result from a failed analysis. Allow 10 to 15 minutes if the project already builds. The examples use Go 1.26.1 on this machine; the installed Debian package is golang-go 2:1.22~2build1, so check your own toolchain before relying on a newer flag.
The route
Jump straight to the step you need, or tick off Done means at the end.
go vet reports suspicious constructs such as mismatched Printf arguments, invalid struct tags, lost cancellation functions and several concurrency mistakes. It uses heuristics. A clean run is useful evidence, not a proof that the program is correct.
1. Confirm the toolchain and enter the module
Run the version check from the project directory. Replace the placeholder path with the directory containing the relevant go.mod file.
$ cd /path/to/your/module
$ go version
go version go1.26.1 linux/amd64
Your version and platform will differ. If the command is missing, stop here and install Go through your normal package or toolchain process. Do not use sudo merely to run a check against source you can already read.
Checkpoint: confirm that the current directory is the module you intend to inspect:
$ go env GOMOD
/path/to/your/module/go.mod
If this prints /dev/null, you are outside a module, or the project deliberately uses another workspace arrangement. Move to the right directory before interpreting any later result.
2. Vet the current package
With no package pattern, go vet checks the package in the current directory. This is the smallest useful first run:
$ go vet
$ printf 'exit status: %s\n' "$?"
exit status: 0
A successful run normally prints nothing. The second command must follow go vet immediately, because shell commands overwrite the previous exit status. A non-zero status means the invocation failed or a problem was reported. Read the diagnostic before changing code.
For a deliberate failure, a diagnostic may look like this:
$ go vet
# example.test
./main.go:8:2: fmt.Printf format %d has arg name of wrong type string
$ printf 'exit status: %s\n' "$?"
exit status: 1
The exact package name, line and wording depend on the source and toolchain. Treat the reported file and line as the place to inspect, not as an instruction to apply an unreviewed edit.
3. Check all packages in the module
For a normal module-wide check, use the recursive package pattern:
$ go vet ./...
$ printf 'exit status: %s\n' "$?"
exit status: 0
The ./... pattern asks the Go command to resolve packages below the current module path. It can take longer than the current-package check and can expose errors in tests or internal packages that the first run did not reach. It does not mean every file anywhere under the filesystem; it is interpreted using Go's package rules.
Run this before sending a change for review or building a release candidate. If it fails, save the complete output with the surrounding command and toolchain version. A useful captured run is:
$ go vet ./... 2> vet.err
$ status=$?
$ sed -n '1,120p' vet.err
$ printf 'exit status: %s\n' "$status"
exit status: 0
Remove the temporary vet.err only after you have copied any needed diagnostics. That file is disposable project output, not a Go source file. Do not commit it unless the project explicitly requires captured analysis logs.
4. Inspect the available analyzers
The default run enables the registered analyzers. List them from the installed toolchain:
$ go tool vet help
vet is a tool for static analysis of Go programs.
...
Registered analyzers:
appends check for missing values after append
atomic check for common mistakes using the sync/atomic package
printf check consistency of Printf format strings and arguments
The list is longer than the excerpt and changes between Go releases. Ask for one analyzer when investigating a particular class of warning:
$ go tool vet help printf
printf: check consistency of Printf format strings and arguments
Use the go vet flags named by that help output, for example -printf=false to disable one check or -printf to enable it explicitly. Keep any exception close to the command or build configuration that needs it, and explain why it is safe. Disabling a check hides reports; it does not make the underlying code safer.
5. Use output modes carefully
Current Go releases provide a JSON mode for tools that need to collect diagnostics:
$ go vet -json ./... > vet.json
$ test -s vet.json && echo 'JSON output written'
The JSON file is generated state and can contain paths from the local machine. Check the project policy before sharing or committing it. The installed command also documents -c for source context and -diff for printing suggested changes.
Do not use -fix as a blind repair step. On this toolchain it can apply the first suggested fix for a diagnostic, which changes source files. Review the diff first with version control, or use -diff where the analyzer supports a suggested patch. If an automated edit is wrong, restore only the affected file from your normal version-control workflow after checking the path and reviewing the diff. Never discard unrelated local work.
6. Add an alternative analyzer only when you need it
The -vettool option selects a different analysis binary. The manual gives the shadow analyzer as an example, but installing an external tool changes your environment and may download code. Treat that as a separate, reviewable dependency decision.
$ command -v shadow
/home/you/go/bin/shadow
$ go vet -vettool="$(command -v shadow)" ./...
If command -v shadow prints nothing, do not continue with the second command. Build or install the chosen analyzer according to its official documentation, then record its version and why the project uses it. The standard go vet run uses the Go tool's default analyzers and does not require this extra binary.
7. Interpret the result without overclaiming
Vet is aimed at likely mistakes and relies on analyser-specific heuristics. It can find errors the compiler misses, but it does not prove that input validation, authorisation, performance, tests or business rules are correct. Keep the output alongside compiler and test results rather than replacing them.
- Exit status 0 means the requested analysis completed without a reported problem.
- A non-zero status means the invocation failed or a diagnostic was reported; read the full output to tell which.
- A package pattern can change what is checked, so record whether you ran
go vet,go vet ./...or a focused package path. - Different Go versions can register different analyzers and flags. Re-run
go versionwhen comparing results from two machines.
No elevated privileges are needed for the commands here. If the source or module cache is unreadable, fix ownership or access through your normal administration process rather than running the whole check as root. Root can make generated files or caches harder to use later and can conceal an ordinary permission problem.
Done means
go env GOMODidentified the intended module.go vet ./...completed with exit status 0, or each reported diagnostic has a recorded decision.- You know which Go version and package pattern produced the result.
- Any JSON, error log or suggested patch was reviewed and is either intentionally retained or removed.
- You have not treated a clean vet run as a replacement for tests, review or security analysis.