go build, run, install & clean
These four commands cover how Go turns source into binaries, executes them locally, installs tools globally, and resets caches when debugging stale builds.
Summary
go build compiles packages into artifacts you ship.
go run is a dev shortcut that compiles to a temp file and runs it immediately.
go install places command binaries on your PATH via GOBIN or GOPATH/bin.
go clean removes build outputs and cache entries when you need a cold rebuild.
All four share the same package loader and honor build tags, GOOS, GOARCH, and module settings.
Recipe
Quick-reference recipe card - copy-paste ready.
# Build a service binary with size-focused flags
go build -trimpath -ldflags="-s -w" -o bin/api ./cmd/api
# Run locally with arguments
go run ./cmd/api --addr :8080
# Install a CLI tool at the module version in go.mod
go install golang.org/x/tools/cmd/goimports@latest
# Clear test result cache after fixing a flaky test
go clean -testcacheWhen to reach for this:
- Use
go buildfor release artifacts, Docker images, and CI binaries. - Use
go runfor quick iteration onmainpackages. - Use
go installfor developer tools (goimports,staticcheck, codegen CLIs). - Use
go clean -cacheonly when diagnosing corrupted or impossible cache hits.
Working Example
# Module layout:
# .
# ├── go.mod
# ├── cmd/seed/main.go
# └── internal/seed/seed.go
go build -o bin/seed ./cmd/seed
./bin/seed --count 5
go run ./cmd/seed --count 3
go install ./cmd/seed # installs to $(go env GOPATH)/bin or GOBIN
go clean -i ./cmd/seed # remove installed binary for this import path// cmd/seed/main.go
package main
import (
"flag"
"fmt"
"example.com/tooldemo/internal/seed"
)
func main() {
n := flag.Int("count", 1, "records to create")
flag.Parse()
fmt.Println(seed.Generate(*n))
}// internal/seed/seed.go
package seed
import "fmt"
func Generate(n int) string {
return fmt.Sprintf("generated %d records", n)
}What this demonstrates:
go build -onames the output explicitly for deploy scripts.go runaccepts the same package path and forwards flags after--when needed.go installwith a relative./cmd/seedinstalls from the current module without a separatego get.go clean -iremoves the installed binary matching that package's import path.
Deep Dive
How It Works
- The loader resolves the package pattern to a import path, applies build constraints, and builds an action graph.
- Compile steps write archive files to GOCACHE; link steps combine archives into executables.
go runlinks to a temporary executable in the OS temp directory and deletes it after exit (unless-workleaves intermediates for inspection).go installskips copying into the current directory; it only updates the install destination.
Build Flags at a Glance
| Flag | Effect |
|---|---|
-o path | Output file name (build) |
-trimpath | Remove file system paths from recorded positions |
-ldflags "..." | Pass flags to the linker (-s -w strips debug info) |
-tags list | Enable comma-separated build tags |
-race | Enable race detector (build/test) |
-mod vendor | Read dependencies from vendor/ |
-a | Force rebuild of all packages (ignore cache) |
go clean Targets
| Invocation | Removes |
|---|---|
go clean | Build artifacts in current package dir |
go clean -cache | Entire build cache (GOCACHE) |
go clean -testcache | Cached pass/fail results from go test |
go clean -modcache | Downloaded modules (GOMODCACHE) |
go clean -i pkg... | Installed binaries/archives for packages |
Go Notes
# Inspect where artifacts go
go env GOCACHE GOMODCACHE GOPATH GOBIN
# Print linker-invoked build ID embedded in binaries
go tool buildid bin/seedGotchas
- Using
go runin production scripts - compiles on every invocation and hides the artifact path. Fix:go buildonce, run the binary. - Forgetting
-oin CI - default output names collide when building multiple commands in one directory. Fix: always set-o bin/<name>. go installwithout a version outside a module -@latestmay jump ahead of CI pins. Fix: run from a module with a recordedrequireor pin@v1.2.3.go clean -modcachein shared CI - forces full re-download and slows every job. Fix: cacheGOMODCACHEbetween runs; clean only on corruption errors.- Cross-compiling cgo packages - needs a cross C toolchain, not just
GOOS/GOARCH. Fix: disable cgo (CGO_ENABLED=0) or install the matching cross compiler. - Stale
-trimpathexpectations - panics still include function names; only file paths are trimmed. Fix: upload symbols separately if you need path-level debugging.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
make / just wrappers | Teams want named targets (make test) | The wrapper hides go flags you need to learn |
goreleaser | Multi-platform releases with archives and checksums | A single go build for one Linux deploy is enough |
| Bazel / Buck | Hermetic builds at huge scale | Small modules where go build is already fast |
go run | Local iteration on main | Production containers or systemd units |
FAQs
Why is my binary huge?
Debug info and symbol tables add size.
Use -ldflags="-s -w" and -trimpath for release builds.
UPX compression is rarely worth the antivirus false positives.
Where does go install put binaries?
GOBIN if set, otherwise GOPATH/bin.
Ensure that directory is on your PATH.
What does -a do?
Forces rebuilding all packages even when cache hits exist.
Use sparingly; it defeats incremental compilation.
Can I build multiple mains in one command?
Pass multiple package paths: go build -o bin/a ./cmd/a -o bin/b ./cmd/b does not work as one invocation.
Build each main separately or use a small shell loop.
Does go clean delete my source?
No.
It removes object files, cached archives, installed binaries, and cache directories - never .go sources.
How do I keep module paths out of binaries?
-trimpath removes compile-time paths.
Combine with private module hosting and GOPRIVATE for fetch-time privacy.
Why does go run feel slow?
It compiles and links on every invocation.
Keep using it for dev; switch to go build for repeated runs of the same code.
What is GOCACHE?
The directory storing build action outputs keyed by inputs.
It makes incremental builds fast and is safe to delete when troubleshooting.
Can install and build use different GOOS?
Yes.
GOOS=linux GOARCH=arm64 go build cross-compiles; the same env vars apply to go install.
When should I use -race on build?
Enable it for test binaries (go test -race) more often than production binaries.
Race-enabled binaries are slower and need more memory.
Related
- The go Command: Build, Test, and Module Lifecycle - action graph and caches
- Go Toolchain Basics - introductory command examples
- Build Tags & Conditional Compilation - tag-gated sources
- Cross-Compilation & Private Module Proxies - GOOS/GOARCH matrix
- Go Toolchain Best Practices - reproducible release builds
Stack 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).