go vet
Purpose and Scope
go vet is the Go toolchain command for finding likely correctness problems in Go programs. Its own README defines vet as a tool that checks correctness, not formatting style or personal preference, by running a suite of tests tailored to classes of errors such as incorrect Printf format verbs and malformed build tags. That positioning matters because vet is often used in the same development loop as go test: tests execute code paths the developer has written assertions for, while vet statically inspects source for patterns that are suspicious even before a test happens to cover them.
Sources: src/cmd/vet/README
The command is intentionally conservative. The README explains that many possible checks have been rejected because they are not appropriate for a tool run frequently by many programmers. A vet diagnostic is not meant to be a broad lint recommendation; it is meant to point at a real or potential bug that could affect compilation or execution. When a project adds go vet to a local workflow, presubmit hook, or continuous integration job, developers should therefore treat findings as issues worth examining rather than as optional style commentary.
Sources: src/cmd/vet/README
The repository implementation shown here is deliberately small at the cmd/vet layer. src/cmd/vet/main.go opens telemetry counters, installs the standard version flag, records a vet/invocations counter, and then hands control to unitchecker.Main with vet.Suite.... In other words, this command package is the executable wrapper around the vet analyzer suite, not the place where individual checks are described one by one. The policy file explains which checks belong in that suite; the main file shows how the shipped command starts it.
Sources: src/cmd/vet/main.go, src/cmd/vet/README
Relevant Source Files
src/cmd/vet/README— defines vet's purpose and the acceptance criteria for adding checks: correctness, frequency, and precision.src/cmd/vet/main.go— implements thecmd/vetexecutable entry point, version flag setup, telemetry counter increment, and analyzer-suite dispatch throughunitchecker.Main(vet.Suite...).
Check-Selection Criteria
The first selection criterion is correctness. The README says vet checks are about correctness, not style, and that an acceptable check must identify real or potential bugs that could cause incorrect compilation or execution. This distinction is important for both users and contributors. Users should not expect vet to enforce every idiom from style guides, and contributors should not propose checks whose main effect is to prefer one correct spelling over another. The bar is whether the reported condition plausibly leads to wrong behavior, not whether the code could be written more elegantly.
Sources: src/cmd/vet/README
The second criterion is frequency. Vet is run every day by many programmers, often as part of every compilation or submission, so every additional check imposes aggregate cost. The README states that even a significant problem may not justify a new default vet check if it finds only a handful of issues across existing programs. This criterion keeps the default suite focused on problems that occur often enough to repay their execution cost across the Go ecosystem, especially because vet is part of routine developer feedback rather than an occasional deep audit.
Sources: src/cmd/vet/README
The third criterion is precision. The README acknowledges that most vet checks are heuristic and can produce false positives and false negatives, but it requires both rates to be very small. A noisy check trains programmers to ignore output; an incomplete check can create false confidence. That is why vet reports should be accurate enough that each one deserves review and complete enough that running the tool provides meaningful confidence. Precision is the practical boundary between a helpful static check and a warning stream that teams eventually disable.
Sources: src/cmd/vet/README
These three criteria work together rather than independently. A proposed analyzer must find correctness bugs, find them often enough to be worth default execution, and report them with enough accuracy to preserve trust. For example, a check that detects a rare but catastrophic condition may fail the frequency test for the everyday suite, while a check that detects common questionable style may fail the correctness test. A check that targets a real and common bug can still be rejected if it cannot distinguish safe code from unsafe code with adequate precision.
Sources: src/cmd/vet/README
System-to-Code Mapping
At the command layer, go vet is represented by the cmd/vet main package. The imports in main.go show the command's immediate dependencies: cmd/internal/objabi for the version flag, cmd/internal/telemetry/counter for telemetry counters, golang.org/x/tools/go/analysis/suite/vet for the suite of analyzers, and golang.org/x/tools/go/analysis/unitchecker for running analyzers as a unit checker. The resulting executable is therefore a thin orchestration point that connects Go command conventions to the analysis framework.
Sources: src/cmd/vet/main.go
The call sequence is short but meaningful. counter.Open() initializes telemetry counter handling before the command records usage. objabi.AddVersionFlag() adds the standard version-reporting behavior expected of Go toolchain commands. counter.Inc("vet/invocations") records that vet was invoked. Finally, unitchecker.Main(vet.Suite...) starts the analyzer driver with the vet suite expanded as arguments, and the source comment notes that this call never returns. This shape keeps command startup behavior close to other toolchain commands while delegating analysis execution to the shared framework.
Sources: src/cmd/vet/main.go
| Concern | Source-level anchor | What it means for users |
|---|---|---|
| Command startup | counter.Open() and counter.Inc("vet/invocations") | The tool records an invocation through Go's telemetry counter mechanism. |
| Version reporting | objabi.AddVersionFlag() | The command participates in standard Go tool version flag behavior. |
| Analyzer suite | vet.Suite... | Vet runs a curated set of analyzers rather than an arbitrary lint catalog. |
| Execution driver | unitchecker.Main(...) | Analyzer execution is delegated to the Go analysis unit checker framework. |
Execution Flow
In a normal development workflow, vet fits after code has been written and before the change is trusted. A developer may run tests with go test to execute package behavior, then run vet to ask whether the source contains known suspicious constructs. The official Go tutorials frame go test as the built-in way to write and execute tests, while vet fills a different role: it can report static correctness risks independent of a particular test input. Treating the two tools as complementary gives teams faster feedback than relying on either one alone.
Sources: src/cmd/vet/README
A practical workflow is to start with the package or module you are changing, run the normal test command, and then run vet over the same scope before submitting. If vet reports an issue, read it as a request to inspect a likely bug, not as an automatic formatting complaint. The README's precision requirement explains why this expectation is reasonable: checks are supposed to be accurate enough that everything reported is worth examining. If a finding is surprising, first confirm whether the code relies on an unusual but correct pattern, then decide whether the code or the check needs attention.
Sources: src/cmd/vet/README
For contributors considering a new vet analyzer, the execution flow starts with the policy rather than with code. The README makes clear that the suite is not open-ended. Before implementation, a proposed check should be evaluated against the three acceptance questions: does it identify correctness bugs, will it find enough real problems to justify cost in routine runs, and can it report with very low false-positive and false-negative rates. Only after those questions have convincing answers does it make sense to think about adding the analyzer to the suite that main.go passes to unitchecker.Main.
Sources: src/cmd/vet/README, src/cmd/vet/main.go
Compact Reference
Use go vet when you want the Go toolchain's curated correctness checks over Go source. The command's public purpose is not to replace tests, fuzzing, code review, or specialized security tools; it is to catch well-understood classes of likely bugs cheaply enough for everyday use. Because the executable dispatches vet.Suite..., users should think of the default behavior as the Go project's selected analyzer set, governed by the README's correctness, frequency, and precision criteria.
Sources: src/cmd/vet/README, src/cmd/vet/main.go
| Item | Concrete name | Source-backed behavior |
|---|---|---|
| Tool | go vet / cmd/vet | Checks correctness of Go programs using a suite of tests for particular error classes. |
| Entry point | func main() | Initializes command support and invokes the analyzer driver. |
| Version flag setup | objabi.AddVersionFlag() | Adds standard version flag support for the command. |
| Telemetry counter | vet/invocations | Incremented when the command starts. |
| Analyzer dispatch | unitchecker.Main(vet.Suite...) | Runs the vet analyzer suite through the unit checker driver and does not return. |
| Check policy | correctness, frequency, precision | Defines the bar for adding checks to the suite. |
Next Steps
For day-to-day development, add vet to the same feedback loop where you already run tests. Start by running it on the packages you changed, fix or justify each diagnostic, and keep in mind that the suite is curated for correctness issues with a high signal-to-noise ratio. For repository contributors, read the policy before proposing new checks and frame any proposal around concrete bugs found in real programs, expected frequency, and evidence that the diagnostic can be precise enough for default use.
Sources: src/cmd/vet/README, src/cmd/vet/main.go
Related pages: testing, go-command, diagnostics, toolchain-command-reference