Modules and go.mod

Go · Practical · 12 min

Every real project depends on other modules, and the module system decides what code you actually build.

A module is a tree of packages versioned together, defined by go.mod at its root:

module example.com/shop

go 1.23

require github.com/google/uuid v1.6.0

The module line is the import path prefix for your packages. The go line sets the minimum language version — and since Go 1.21, toolchains will download a newer Go if a module needs it (a toolchain line can pin one).

Day-to-day commands:

  • go get example.com/lib@v1.4.0 adds or upgrades a dependency (@latest for the newest release).
  • go mod tidy adds missing requirements and removes unused ones. Run it before committing.
  • go list -m all shows the full dependency graph; go mod why -m X explains why X is needed.

go.sum records cryptographic hashes of every module version used; commit it. Downloads go through the module proxy (proxy.golang.org) and are verified against the public checksum database.

Versions follow semantic versioning, and Go uses minimal version selection: it picks the lowest version satisfying every requirement, so builds are reproducible without a lock file. A breaking change (v2+) must change the import path to example.com/lib/v2, so v1 and v2 can coexist.

For local development across modules, go work init ./app ./lib creates a go.work workspace that builds them together; a replace directive in go.mod does the same for one module. Private repositories need GOPRIVATE=github.com/yourorg/* so the proxy and checksum database are skipped.

Example

// Typical workflow in a terminal:
//
//	go mod init example.com/shop
//	go get github.com/google/uuid@latest
//	go mod tidy
//
// main.go
package main

import (
	"fmt"

	"github.com/google/uuid"
)

func main() {
	fmt.Println(uuid.NewString()) // e.g. 1b4e28ba-2fa1-11d2-883f-0016d3cca427
}

Remember

  • go.mod declares the module path, Go version and requirements
  • go mod tidy keeps requirements accurate; commit go.mod and go.sum
  • Major versions v2+ live at a different import path (/v2)

Watch out for

  • Forgetting to commit go.sum, or editing go.mod by hand instead of using go get / go mod tidy.

Check yourself

  1. Module A needs lib v1.2.0 and module B needs lib v1.4.0. Which version does Go select (v1.5.0 also exists)?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: go.dev/doc/modules/gomod-ref