Go Modules Reference: go.mod, go.sum, Commands, Workspaces, GOPROXY & Private Repos
Go Modules (introduced in Go 1.11, stable in 1.13) is Go’s dependency management system. go.mod declares your module path and dependencies; go.sum is the cryptographic checksum file. Understanding module commands, versioning, and common gotchas will save you hours of debugging dependency issues.
1. go.mod — File Structure & Module Path
What every field in go.mod means
# go.mod example:
module github.com/my-org/my-service # module path — must match repo URL for public modules
go 1.22 # minimum Go version required (not the version you compiled with)
require (
github.com/gin-gonic/gin v1.9.1 # direct dependency
github.com/stretchr/testify v1.8.4 // indirect comment below
golang.org/x/net v0.20.0 // indirect
)
# // indirect = not directly imported in your code (transitive dep kept in go.mod for reproducibility)
# After 'go mod tidy', all indirect deps are listed here
replace (
github.com/some/module v1.2.3 => ./local-fork # replace with local version
github.com/some/module v1.2.3 => github.com/my-fork/module v1.2.4 # replace with fork
)
retract v1.0.0 # mark version as unsafe (appears in go list, warns users to upgrade)
# go.sum — DO commit this file; DO NOT edit manually:
# github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
# github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
# (two lines per dep: source hash + go.mod hash)
2. Essential Commands
go mod init, tidy, download, vendor, verify, why
# Initialize a new module: go mod init github.com/my-org/my-service # Add a dependency (automatically updates go.mod + go.sum): go get github.com/gin-gonic/gin@v1.9.1 # specific version go get github.com/gin-gonic/gin@latest # latest release go get github.com/gin-gonic/gin@main # latest commit on main branch go get github.com/gin-gonic/gin@v2 # major version 2 # Remove unused deps + add missing transitive deps: go mod tidy # Run this: after deleting imports, after adding new imports, before committing # Download all deps to local cache ($GOPATH/pkg/mod): go mod download # Vendor mode (copy deps into ./vendor/ — for reproducible offline builds): go mod vendor go build -mod=vendor ./... # use vendor/ instead of cache # Verify deps haven't been tampered with (compares against go.sum): go mod verify # Why is this package a dependency? go mod why github.com/some/package # List all deps (including transitive): go list -m all # Check for available updates: go list -m -u all | grep "\[" # shows available upgrades in brackets # Output: github.com/gin-gonic/gin v1.9.1 [v1.9.1 → v2.0.0] # Upgrade all deps to latest minor/patch: go get -u ./... go mod tidy
3. Versioning & Semver
Semantic import versioning, pseudo-versions, and pre-releases
# Go module versioning rules: # v0.x.y — no stability guarantees (breaking changes OK) # v1.x.y — stable, no breaking changes in minor/patch # v2+ — MUST have /v2 in module path (semantic import versioning) # Using a v2+ module: import "github.com/some/module/v2" # /v2 is REQUIRED in import path # In go.mod: require github.com/some/module/v2 v2.1.0 # Pseudo-versions (when using a commit, not a tag): go get github.com/some/module@abc1234 # specific commit # go.mod shows: github.com/some/module v0.0.0-20240301123456-abc1234abcde # Format: vX.Y.Z-yyyymmddhhmmss-12hexdigits # Pre-release versions: go get github.com/some/module@v1.3.0-beta.1 go get github.com/some/module@v1.3.0-rc.2 # Minimal version selection (MVS) — Go's algorithm: # When multiple deps require different versions of the same package, # Go picks the MINIMUM version that satisfies ALL constraints. # No "latest" auto-upgrade — you always know exactly what version you get. # This is why go.sum is stable and builds are reproducible. # Downgrade a dep: go get github.com/gin-gonic/gin@v1.8.0 # pin to older version # Exclude a broken version: # In go.mod: exclude github.com/some/module v1.2.0 # skip this specific version
4. Workspaces (Go 1.18+)
go.work for multi-module local development without replace directives
# Problem: developing two modules simultaneously (my-app + my-lib) # Old way: use 'replace' in go.mod to point at local fork — messy, easy to commit by mistake # Better: go workspaces (go 1.18+) # Project structure: # ~/projects/ # my-app/ go.mod (requires my-lib v1.2.0) # my-lib/ go.mod # Initialize workspace: cd ~/projects go work init ./my-app ./my-lib # Creates go.work file: # go 1.22 # use ./my-app # use ./my-lib # my-app now automatically uses local my-lib (no replace needed) go work sync # sync workspace with go.mod dependencies # Add another module to workspace: go work use ./another-module # go.work vs go.work.sum: # go.work — commit if you want team to share workspace config # .gitignore go.work for personal dev setups that shouldn't affect team # Run commands in workspace context: cd my-app && go build ./... # uses local my-lib automatically go test ./... # tests across all workspace modules # Disable workspace temporarily: GOWORK=off go build ./... # ignores go.work, uses go.mod as-is
5. GOPROXY, GOPRIVATE & Module Mirror
Control where Go downloads modules — proxy, private repos, GONOSUMCHECK
# Default GOPROXY chain: # GOPROXY=https://proxy.golang.org,direct # 1. Try proxy.golang.org (Google's module mirror) — fast + cached # 2. If not found: try direct (original VCS) # Check/set proxy: go env GOPROXY go env -w GOPROXY=https://proxy.golang.org,direct # Private repos (don't go through public proxy): go env -w GOPRIVATE=github.com/my-private-org,gitlab.com/internal-group # GOPRIVATE also sets GONOSUMCHECK (skip checksum verification for private modules) # For just skipping checksum: go env -w GONOSUMCHECK=github.com/my-private-org # Corporate proxy (air-gapped environments): go env -w GOPROXY=https://my-corp-proxy.internal,off # 'off' means fail if proxy doesn't have it (don't try direct) # Athens — self-hosted module proxy (for air-gapped or compliance): # docker run -p 3000:3000 gomithrandir/athens:latest go env -w GOPROXY=http://localhost:3000,direct # Common CI setup (fast + offline-safe): # 1. Download all deps first: go mod download # 2. Build using cache (no network needed): GOFLAGS="-mod=readonly" go build ./... # -mod=readonly: fail if go.mod needs updating (catches "forgot to run go mod tidy") # Debugging module issues: GOFLAGS=-v go get github.com/some/module # verbose download go env GOPATH # where modules cache lives ls $(go env GOPATH)/pkg/mod/cache/download # inspect the module cache
Track Go releases and module tooling updates.
ReleaseRun monitors Kubernetes, Docker, and 13+ DevOps technologies.
Related: Go Reference | GitHub Actions Reference | Trivy Reference | Go EOL Tracker
🔍 Free tool: Go Module Health Checker — check any Go module for latest version, known CVEs, and active maintenance — before go get.
Founded
2023 in London, UK
Contact
hello@releaserun.com