Every real Go project has a go.mod file declaring what it depends on, and a go.sum file most people never read — understanding what each one actually does removes a lot of mystery from the first minutes of touching any Go codebase.
2 min read
A module is a collection of Go packages versioned and distributed
together — the standard unit of dependency management in Go. Every module
has a go.mod file at its root:
module github.com/yourname/yourproject
go 1.22
require (
github.com/gin-gonic/gin v1.9.1
github.com/stretchr/testify v1.8.4
)
module declares the project's own import path — how other code
would import it, and how its own internal packages reference each other.go 1.22 declares the minimum Go language version the project
requires.require lists direct dependencies and the exact version of each one
currently in use.$ go mod init github.com/yourname/yourproject # creates go.mod for a new project
$ go get github.com/gin-gonic/gin # adds a dependency, updates go.mod
$ go mod tidy # adds missing deps, removes unused onesAlongside go.mod, Go maintains a go.sum file containing a cryptographic
checksum for every dependency (and every dependency of a dependency) used
in the project:
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
Its entire job is verifying that whatever gets downloaded matches exactly
what was recorded before — if a dependency's published code ever changed
unexpectedly (a compromised package registry, a tampered release), the
checksum wouldn't match, and go build would refuse to proceed rather than
silently using different code than what was originally verified. This is a
real, practical supply-chain security mechanism, not just bookkeeping.
Go dependency versions follow semver (vMAJOR.MINOR.PATCH) — a patch
bump (v1.9.1 → v1.9.2) should only contain bug fixes, a minor bump
(v1.9.x → v1.10.0) should only add backward-compatible features, and a
major bump (v1.x.x → v2.0.0) signals a breaking change. go get won't
silently jump you across a major version: Go requires a module at v2 or higher
to include the major version in its import path (github.com/you/lib/v2), so
moving to a new major version is an explicit change to your imports, not a
routine upgrade.
Cloning any real Go project and running go build ./... is the standard
first step before touching any code — Go fetches whatever go.mod lists on
its own (go mod download fetches without building). go mod tidy is for
changing the dependency list, not for setting up a fresh clone, since it
rewrites go.mod and go.sum. Knowing that go.mod declares intent (what
versions should be used) while go.sum verifies what was actually
downloaded matches is the difference between understanding these files and
treating them as unreadable auto-generated noise to avoid touching.
Check your understanding
A quick comprehension check — not tracked, not graded, just for you.
1. What does go.mod's `require` section list?
2. What is go.sum's actual job?
3. Under semantic versioning, what does bumping from v1.9.1 to v2.0.0 signal?
Go