golang/go
Go command
cmd/go is the program a user actually invokes: go build, go test, go get, go run, go mod, go work, go install, go env, and so on. It's the orchestrator that resolves modules, walks import graphs, schedules per-package builds, manages the build cache, and shells out to compile, link, asm, cgo, and vet.
Purpose
The go command is the public face of the Go toolchain. Internally, it does three big things:
- Module resolution — given a
go.mod, decide which versions of which modules to use. - Package loading — turn a list of import paths into a graph of packages and their files.
- Build orchestration — drive the per-package compile/assemble/link calls, with a content-addressed build cache.
It also hosts a long list of subcommands (mod, work, vet, test, etc.), each of which lives in its own internal package.
Directory layout
src/cmd/go/
├── main.go # main + dispatch table of subcommands
├── alldocs.go # Generated; concatenated subcommand help
└── internal/
├── base/ # Subcommand framework, common flags
├── work/ # The build engine (build, install, test, run)
├── load/ # Package loader (resolves imports → *Package)
├── modload/ # Module loader (resolves go.mod → resolved versions)
├── modfetch/ # Download + cache modules from proxies
├── modindex/ # On-disk index of stdlib + modcache
├── modcmd/ # 'go mod' subcommands (init, tidy, edit, why, ...)
├── modget/ # 'go get' (modify go.mod)
├── modinfo/ # JSON-export of module info
├── mvs/ # Minimum version selection algorithm
├── workcmd/ # 'go work' (workspace mode)
├── toolchain/ # 'go.mod' toolchain= switching, re-exec
├── vcs/ # VCS proxy (git/hg/svn) for module resolution
├── vcweb/ # Test-only VCS server
├── auth/ # 'go env GOAUTH' authenticated downloads
├── cache/ # Content-addressed build/test cache
├── cacheprog/ # External cache helper protocol
├── cfg/ # GO* environment variable handling
├── cmdflag/ # Subcommand flag helper
├── doc/ # 'go doc'
├── envcmd/ # 'go env'
├── fmtcmd/ # 'go fmt'
├── fsys/ # Overlay-aware filesystem (used by gopls)
├── generate/ # 'go generate'
├── gover/ # Go version comparison ('go1.21' vs 'go1.22')
├── help/ # Help registry
├── imports/ # Build-tag-aware import discovery
├── list/ # 'go list' (dump package info)
├── lockedfile/ # File locking for concurrent invocations
├── mmap/ # mmap helper
├── run/ # 'go run'
├── search/ # Path patterns ('./...' resolution)
├── str/ # String helpers
├── telemetrycmd/ # 'go telemetry'
├── telemetrystats/ # Counter declarations
├── test/ # 'go test'
├── tool/ # 'go tool' (delegate to subtools)
├── trace/ # 'go run -toolexec=trace'-style support
├── version/ # 'go version'
├── vet/ # 'go vet'
├── web/ # HTTP fetcher
└── fips140/ # FIPS-140 compliance helpersSubcommands
cmd/go/main.go builds a flat dispatch table of *base.Command. Each subcommand is registered from its package's init or via the table in main.go:
base.Go.Commands = []*base.Command{
bug.CmdBug, // go bug
work.CmdBuild, // go build
clean.CmdClean, // go clean
doc.CmdDoc, // go doc
envcmd.CmdEnv, // go env
vet.CmdFix, // go fix
fmtcmd.CmdFmt, // go fmt
generate.CmdGenerate, // go generate
modget.CmdGet, // go get
work.CmdInstall, // go install
list.CmdList, // go list
modcmd.CmdMod, // go mod
workcmd.CmdWork, // go work
run.CmdRun, // go run
telemetrycmd.CmdTelemetry, // go telemetry
test.CmdTest, // go test
tool.CmdTool, // go tool
version.CmdVersion, // go version
vet.CmdVet, // go vet
...
}Each *base.Command has a Run function (func(ctx, *Command, []string)), help text, and flags. The base package handles flag parsing, help routing, and "did you mean" suggestions.
How go build works
graph TD
Start[go build .] --> Args[parse flags + args]
Args --> Modload[modload.LoadPackages]
Modload --> Mvs[mvs: pick versions]
Mvs --> Loader[load.PackagesAndErrors]
Loader -->|per package: parse files,<br/>resolve imports| PkgGraph[Package graph]
PkgGraph --> Builder[work.Builder]
Builder --> Actions[Plan Action graph]
Actions -->|leaf| Compile[Action: compile pkg]
Actions -->|leaf| Asm[Action: assemble .s]
Actions -->|root| Link[Action: link]
Compile -.cache hit?.-> Cache[build cache]
Compile -->|miss| Toolchain[exec compile]
Link --> Binary[Output binary]Concretely:
cmd/go/internal/work.runBuildparses build flags (-o,-tags,-gcflags,-ldflags,-trimpath, etc.).modload.LoadPackagesresolves modules using Minimum Version Selection (internal/mvs), readinggo.modandgo.sum. Missing modules trigger a download viainternal/modfetch.load.PackagesAndErrorswalks each requested package, parses imports, applies build tags (internal/imports/build.go), and produces*load.Packagenodes.work.Builder.Doplans anActionDAG: one action per package compile, plus dependencies, plus a final link action.- The builder executes actions in topological order, in parallel up to
-p N(default = NumCPU). Each action consults the build cache (internal/cache). - Cache misses shell out to
$GOROOT/pkg/tool/<host>/compile,link,asm,cgo, etc.
Module loading
The module loader is the most complex part of the go command. It handles:
- Reading and editing
go.modandgo.sum. - Resolving the build list — the set of module versions that satisfy all
requiredirectives. - Downloading modules through the proxy (
proxy.golang.orgby default) viainternal/modfetch. - Verifying checksums against
sum.golang.org(the public checksum database). - Workspace mode (
go.work), which stitches together multiple modules.
The core algorithm is Minimum Version Selection (MVS) in internal/mvs/. Given a root module's requirements, MVS picks the minimum version of each module that all transitively-required versions agree on.
Module operations
go mod init— create ago.mod.go mod tidy— add missing requirements, remove unused ones; fully consistent set.go mod download— fetch and cache; do not changego.mod.go mod graph— print the require graph as DAG edges.go mod vendor— copy all dependencies into./vendor/.go mod why -m mod— explain why a module is in the graph.go mod edit— programmatic edit ofgo.mod.
All implemented under internal/modcmd/.
Toolchain switching
Since Go 1.21, the go directive in go.mod may declare a Go language version higher than the current toolchain. The go.mod toolchain line and the GOTOOLCHAIN env var let the go command re-exec a different Go release that satisfies the requirement.
This logic lives in internal/toolchain/. The first go invocation downloads the requested toolchain into GOPATH/pkg/mod/golang.org/toolchain@<version> and execs into it. Users see this as a transparent "this project requires Go 1.22; I'll go fetch it."
The build cache
internal/cache/cache.go is a content-addressed, on-disk cache, by default at ~/.cache/go-build. Cache keys are derived from:
- The action ID: hash of all inputs (source files, dependencies, compiler flags, target OS/arch, toolchain version, ...).
- The output ID: hash of the action's output object file.
Cache lookups are cheap; cache hits skip the corresponding compile/link/vet invocation. go clean -cache wipes it.
go test results are also cached: a successful test run caches a "test passed" record keyed on the same input set. Subsequent identical go test invocations print (cached) and skip the run.
For build systems that want to plug in their own remote cache, the GOCACHEPROG protocol (handled by internal/cacheprog/) lets an external program take over.
go test
internal/test/ orchestrates test runs. For each tested package, go test:
- Builds the package's tests by writing a synthesized
_testmain.gothat calls into the framework. - Compiles + links a test binary.
- Runs the binary, parses
go test -voutput, optionally streams tocmd/test2json. - Caches a "passed" record on success.
Special test modes:
-cover,-coverpkg— coverage instrumentation viainternal/cov/.-fuzz,-fuzztime— fuzzing viasrc/internal/fuzz/.-race,-asan,-msan— sanitizer modes (require cgo).-bench,-benchtime,-benchmem— benchmark mode.
go generate
internal/generate/ walks files matching //go:generate <command> and runs them in the file's directory. Used to regenerate code from rule files, schemas, etc.
go env
internal/envcmd/ reads/writes ~/.config/go/env. The defaults are seeded by $GOROOT/go.env. The hierarchy is:
- Environment variables override everything.
- Per-user
go envsettings. - The
$GOROOT/go.envdefaults.
go vet
internal/vet/ is a thin wrapper that invokes cmd/vet/ (a separate binary) on each package built. The vet binary uses golang.org/x/tools/go/analysis (vendored under src/cmd/vendor/) and bundles the standard analyses.
Key abstractions
| Abstraction | Where | Purpose |
|---|---|---|
*base.Command |
cmd/go/internal/base/ |
One subcommand |
*load.Package |
cmd/go/internal/load/ |
One Go package, fully resolved |
*work.Action |
cmd/go/internal/work/ |
One step in the build DAG |
modload.requirementsBuilder |
cmd/go/internal/modload/ |
The module loader's build list |
mvs.Reqs |
cmd/go/internal/mvs/ |
The interface MVS consumes |
cache.Cache |
cmd/go/internal/cache/ |
The build cache |
imports.Tags |
cmd/go/internal/imports/ |
Build constraint evaluation |
Key source files
| File | Purpose |
|---|---|
src/cmd/go/main.go |
Entry point + subcommand dispatch |
src/cmd/go/internal/work/build.go |
go build driver |
src/cmd/go/internal/work/exec.go |
Action executor |
src/cmd/go/internal/work/action.go |
Action DAG construction |
src/cmd/go/internal/load/pkg.go |
Package loader |
src/cmd/go/internal/modload/load.go |
Module loader |
src/cmd/go/internal/modload/buildlist.go |
Build list (MVS result) |
src/cmd/go/internal/modfetch/fetch.go |
Module download + verify |
src/cmd/go/internal/cache/cache.go |
Build cache |
src/cmd/go/internal/test/test.go |
go test driver |
src/cmd/go/internal/toolchain/select.go |
Toolchain switching |
Integration points
- Compiler (compiler) is invoked via
exec.Commandfrominternal/work/. - Linker (linker) is invoked the same way as the final step.
- Module proxy (
proxy.golang.org,sum.golang.org) is contacted viainternal/modfetchandinternal/web. goplsand other tools call into similar logic viagolang.org/x/tools/go/packages, which is a separate but parallel implementation that talks togo listto extract package info.
Entry points for modification
- New subcommand: add a
*base.Commandand register it inmain.go. Don't forgetalldocs.go(regenerated bygo generate ./...). - Module loader bug: start in
cmd/go/internal/modload/. The integration tests are incmd/go/script_test.goplus thetxtarfiles undercmd/go/testdata/script/. - Build cache:
internal/cache/.cmd/go/script_test.gohas many cache-related tests. - Test framework:
cmd/go/internal/test/plus thetestingpackage itself insrc/testing/.
Testing the go command
cmd/go/script_test.go is the workhorse: it runs scripts written in the txtar format (sibling to the cmd/go/testdata/script/ directory). Each script can cd, cp, go build, etc., and assert about output and file contents. New go command behaviors usually get a script test.
Where to read next
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.