Skip to content

Intermediate · Packages, testing and generics · topic 22 of 46 · 30 min

Dependencies with Go modules

Explanation

go get adds or updates a dependency and records it in go.mod; go.sum stores checksums so downloads cannot be tampered with. go mod tidy adds what is missing and removes what is unused. Versions follow semantic versioning, and from v2 onwards the major version is part of the import path, like github.com/jackc/pgx/v5.

What a dependency is

A dependency is someone else's module that your code uses, for example a router, a database driver or a UUID generator. Go downloads modules from their source (usually a Git repository) through a module proxy, by default proxy.golang.org, a Google-run cache that keeps versions available even if the original repo disappears.

Adding a dependency

bash
go get github.com/google/uuid@latest
go mod tidy
go get downloads the module and adds it to go.mod. go mod tidy cleans up after you add or remove imports.
go
package main

import (
	"fmt"

	"github.com/google/uuid"
)

func main() {
	fmt.Println("order id:", uuid.NewString())
}
Third-party imports are usually grouped after standard-library imports, separated by a blank line (goimports does this for you).
output
module example.com/orders

go 1.24

require github.com/google/uuid v1.6.0
go.mod after go get. Dependencies of your dependencies may appear with a // indirect comment.

go.sum: fingerprints

go.sum lists a cryptographic hash for every module version your build uses. If a download ever differs from the recorded hash, the build stops. Go also checks hashes against a public checksum database (sum.golang.org), so a malicious change to a published version would be noticed. Commit go.sum together with go.mod.

Semantic versions

PartExample changeMeaning
MAJOR (v1 → v2)v1.9.0 → v2.0.0Breaking change: code using it may need edits
MINOR (v1.4 → v1.5)v1.4.2 → v1.5.0New features, still compatible
PATCH (v1.4.2 → v1.4.3)v1.4.2 → v1.4.3Bug fixes only
v0.x.yv0.3.1Still unstable: anything may change

Go's rule for major versions: from v2 on, the module path ends with /v2, /v3 and so on. So v4 and v5 of pgx are different import paths (github.com/jackc/pgx/v4 and github.com/jackc/pgx/v5), and a program can even use both during a migration.

Everyday commands

CommandWhat it does
go get example.com/lib@v1.4.0Use exactly v1.4.0
go get -u ./...Update dependencies to newer minor/patch versions
go get example.com/lib@noneRemove a dependency
go mod tidyAdd missing and remove unused requirements
go list -m allList every module in the build
go list -m -u allShow which modules have updates
go mod why -m example.com/libExplain why a module is needed
go install example.com/tool@latestInstall a command-line tool into GOPATH/bin

How Go picks versions

Go uses minimal version selection: for each module it picks the lowest version that satisfies every requirement in the build, not the newest one available. Builds therefore stay the same until someone deliberately changes go.mod. There is no separate lock file; go.mod plus go.sum is the lock.

Staying safe

  • Prefer the standard library when it is good enough. Every dependency is code you must trust and update.
  • Check a library before adding it: recent commits, a clear licence, real users, tests.
  • Run govulncheck regularly. It reports known vulnerabilities that your code actually calls: go install golang.org/x/vuln/cmd/govulncheck@latest, then govulncheck ./...
  • For private company repositories, set GOPRIVATE (for example GOPRIVATE=github.com/yourcompany/*) so Go fetches them directly and does not send their names to the public proxy or checksum database.
Tip: A replace line in go.mod (replace example.com/lib => ../lib) points a dependency at a local folder while you develop both together. Remove it before you publish.
Careful: Common mistake: editing go.mod by hand and forgetting go.sum, or committing go.mod without go.sum. Let go get and go mod tidy update both, then commit both files.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Dependencies with Go modules · 1/7

Dependencies

Real projects use other people's modules. Go modules manage them for you.

Prefer a video by a teacher? Find free videos on “go modules go get go mod tidy go.sum explained” on YouTube ↗

In real life: Adding a Postgres driver to an expense API

A team adds pgx v5 to talk to PostgreSQL. One go get records the version in go.mod and the checksums in go.sum. In CI, every build downloads exactly the same versions. Each month a developer runs go list -m -u all and govulncheck ./..., updates what is safe, runs the tests, and commits the two changed files.

bash
go get github.com/jackc/pgx/v5@latest
go mod tidy
go build ./...
go test ./...
govulncheck ./...
git add go.mod go.sum
The import path includes /v5 because pgx is past v1.

Practice (0/4 done)

Task 1 · Question

You removed the last import of a library from your code. Which command removes it from go.mod?

Task 2 · Question

A library releases v3.0.0. What is its import path?

Task 3 · Question

What does go.sum protect against?

Task 4 · Practice

In a new module, add github.com/google/uuid, print a new UUID, then look at go.mod and go.sum. Finally install and run govulncheck on the module.

Quick quiz

Question 1

1.Which version change usually means breaking changes?

Question 2

2.How does Go choose a dependency version by default?

Question 3

3.What does GOPRIVATE do?

Question 4

4.How do you install a Go command-line tool at a version?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

Which version change usually means breaking changes?

Answer: Major

Semantic versioning reserves major versions for incompatible changes.

How does Go choose a dependency version by default?

Answer: The minimal version that satisfies all requirements

Minimal version selection keeps builds reproducible.

What does GOPRIVATE do?

Answer: Tells Go to fetch matching modules directly, not through the public proxy and checksum database

Use it for company-internal repositories.

How do you install a Go command-line tool at a version?

Answer: go install path@version

go install path@version builds the tool and puts it in GOPATH/bin (or GOBIN).

What is go.sum for?Related

Answer: It stores checksums of dependencies so tampered downloads are detected

go.sum holds a cryptographic checksum for every dependency version used.

From Your first program and Go modules

Since the last release v3.1.4 there are commits: "fix: login timeout" and "feat: export to PDF". What is the next version?Related

Answer: 3.2.0

The feat is the highest change, so MINOR is bumped and PATCH reset: 3.2.0.

From Semantic versioning, tags and releases

Does "^2.3.0" allow version 3.0.0?Related

Answer: No

A caret never allows a new major version.

From Node.js basics

Which command downloads the packages listed in pubspec.yaml?Related

Answer: flutter pub get

pub get resolves and downloads dependencies.

From Packages and pub

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 3 more topics in “Packages, testing and generics” before its exam: Testing with go test, Benchmarks and fuzz tests, Generics: type parameters and constraints.
  2. Module 5 exam: Packages, testing and generics · 14 questions · 25 min, without help. 5 topics of this module still to finish first.
  3. Then the next module, Concurrency: goroutines, channels and context. 46 topics left in the course before the final exam.

← Previous: Packages, visibility and project layout