Before this:Packages & modules
Dependency management
Key takeaways
A module’s dependencies live in go.mod (what versions you require) and
go.sum (checksums that prove those versions haven’t changed). go get adds
or upgrades a dependency; go mod tidy syncs the files to what your code actually
imports. Versions follow semantic versioning, and the checksums give you
reproducible builds — everyone compiles the exact same code.
Every non-trivial program uses code someone else wrote. This lesson covers how Go tracks that code, building on Packages & modules.
go.mod and go.sum
A module is a tree of packages with a go.mod at its root. It declares the module
path, the Go version, and each dependency’s version:
module github.com/example/gophertrunk
go 1.22
require (
github.com/some/dsp v1.4.2
golang.org/x/sync v0.7.0
)
Alongside it, go.sum stores a checksum for every module version the build uses.
When the toolchain downloads a dependency, it verifies the bytes against go.sum —
so a tampered or changed release fails the build instead of silently slipping in.
Adding and updating dependencies
You rarely edit go.mod by hand. The commands do it:
| Command | What it does |
|---|---|
go get github.com/some/dsp@v1.5.0 |
Add or move to a specific version |
go get -u ./... |
Upgrade dependencies to newer minor/patch versions |
go mod tidy |
Add missing and drop unused dependencies |
go mod download |
Fetch everything go.mod lists into the cache |
go mod verify |
Check the cache matches go.sum |
Just importing a package and running go mod tidy is the usual way to pick up a new
dependency — the tool finds the import, resolves a version, and records both files.
Semantic versioning
Go leans hard on semver — vMAJOR.MINOR.PATCH. A patch or minor bump promises
backward compatibility; a major bump (v2+) is a breaking change and, by Go’s
import-compatibility rule, even changes the import path (.../dsp/v2). This is what
lets go get -u safely pull bug fixes without breaking your build.
Why a small dependency tree matters
Every dependency is code you now ship, trust, and must keep updated. Go’s culture —
and GopherTrunk’s — favours a lean tree: reach for the
standard library first, add a
dependency only when it earns its place. Fewer dependencies means faster builds, a
smaller attack surface, and less breakage when you upgrade. For fully offline or
audited builds, go mod vendor copies dependencies into a vendor/ directory that
the build uses instead of the network.
Quick check: what is the job of the go.sum file?
Recap
go.moddeclares required dependency versions;go.sumstores checksums to verify them.go getadds/upgrades;go mod tidysyncs the files to real imports.- Versions follow semantic versioning; a major bump changes the import path.
- Prefer a small dependency tree;
go mod vendorsupports offline builds.
Next up: error-handling patterns beyond the basic if err != nil.
Frequently asked questions
What's the difference between go.mod and go.sum?
go.mod lists your module’s path, its Go version, and the versions of the dependencies you require — it’s the human-readable declaration. go.sum records a cryptographic checksum for every module version, so the toolchain can verify that what it downloads is byte-for-byte what you locked. go.mod says what; go.sum proves it hasn’t changed.
What does go mod tidy do?
It reconciles go.mod and go.sum with what your code actually imports — adding any dependency you use but haven’t declared, and removing any you declared but no longer import. Running it keeps the module files honest, which is why it’s a common pre-commit step.