Skip to content

Go Modules

A module is a collection of Go packages that are versioned together and distributed as a unit. Every modern Go project starts with a module. The module system replaced the old GOPATH workflow in Go 1.11 and became the default in Go 1.16.

Playground note: go mod commands require the go binary and a file system — they cannot run in the in-browser runner. Follow the steps below in your terminal.

Terminal window
mkdir myapp && cd myapp
go mod init github.com/yourname/myapp

This creates a go.mod file — the module’s manifest:

module github.com/yourname/myapp
go 1.22

The module path (github.com/yourname/myapp) is both the import path prefix for your own packages and the identifier other modules use when they depend on yours. It does not have to be a real URL during development, but it must be unique if you publish to the Go module proxy.

After adding a dependency you will find two files in the root of your module:

go.mod — declares the module path, the minimum Go version, and all direct and indirect dependencies:

module github.com/yourname/myapp
go 1.22
require (
github.com/go-chi/chi/v5 v5.1.0
golang.org/x/text v0.14.0 // indirect
)

go.sum — a cryptographic checksum ledger. Every dependency’s zip archive and go.mod are hashed here. The Go toolchain verifies these hashes on every build to guarantee reproducibility and protect against supply-chain attacks. Commit both files to version control.

Terminal window
# Add the latest version of a module
go get github.com/go-chi/chi/v5
# Add a specific version
go get github.com/go-chi/chi/[email protected]
# Upgrade a dependency to its latest patch/minor release
go get -u github.com/go-chi/chi/v5

After go get, your source code can import the package:

import "github.com/go-chi/chi/v5"

Over time your code and your dependencies can drift apart — you might delete an import or add one without running go get. go mod tidy fixes both:

Terminal window
go mod tidy

It adds any missing require lines, removes require lines for packages no longer imported, and updates go.sum to match. Run it before every commit.

Go enforces a rule called semantic import versioning: if a module releases a v2 or higher, the import path must include the major version suffix.

Terminal window
# v1 — no suffix needed
go get github.com/foo/[email protected]
# import "github.com/foo/bar"
# v2+ — /v2 suffix is part of the import path
go get github.com/foo/bar/[email protected]
# import "github.com/foo/bar/v2"

This means two major versions of the same module can coexist in the same binary without conflict. The import path change is intentional: a v2 API is allowed to be incompatible with v1.

Which command initialises a new Go module in the current directory?
What is the purpose of go.sum?
What does go mod tidy do?
A module releases v2.0.0 with breaking changes. How must the import path change?