Modules and go.mod

go mod init creates go.mod, which names your module and its dependencies, while go.sum holds the hashes that prove they did not change.

Syntaxgo mod init <module-path>

A module is a set of packages released and versioned together. It is also what the go command downloads when your code needs somebody else's work. A module's root is simply the directory holding a file named go.mod, and one command creates that file: go mod init example.com/greet.

What go.mod records

The module line is the module path. It is also the import prefix for everything inside, so a package in the text folder is imported as example.com/greet/text. The go line gives the Go version the code is written for. Each require line names one dependency and its version. Since Go 1.21 an optional toolchain line can ask for a specific toolchain. Let the tools write this file: go get adds a dependency, and go mod tidy adds whatever your code imports and drops whatever it no longer does.

What go.sum records

go.sum holds hashes — short fingerprints — of each dependency's content and of its go.mod. Every build checks downloads against them, so a dependency that changed under you fails the build instead of running. go.sum is not the list of versions; that is go.mod. Commit both files.

Why the path is a URL

Go has no central registry, so the import path is the address. go get github.com/google/uuid finds the code from the path itself, by default through the module proxy at proxy.golang.org (the default since Go 1.13). A private program can use any unique path, but publish only under a path you control.

Shorthand and longhand

require github.com/google/uuid v1.6.0

require (
	github.com/google/uuid v1.6.0
)

Both forms mean the same; the bracketed block just groups several requirements.

Example

Example · go
// Set up in an empty directory:
//   go mod init example.com/greet
//   go run .
package main

import "fmt"

func main() {
	// := declares a new variable and gives it a value in one step.
	module := "example.com/greet"

	// A package's import path is the module path plus its folder inside the module.
	fmt.Println("import prefix:", module)
	fmt.Println("package in folder text:", module+"/text")
}

// Output:
// import prefix: example.com/greet
// package in folder text: example.com/greet/text

When to use it

  • Start a repository that other projects will import by its URL.
  • Add a third-party library and keep the exact version recorded for the whole team.
  • Explain to a reviewer why both go.mod and go.sum belong in the commit.

More examples

A go.mod file, line by line

This is the whole file for a small program with one dependency. Real projects grow a bracketed require block, and some lines gain an // indirect comment, which marks a module your code does not import directly but a dependency of yours needs.

Example · text
module example.com/greet          // the module path, and the import prefix for its packages

go 1.27                           // the Go version this code is written for

require github.com/google/uuid v1.6.0   // one dependency, at one exact version

What go.sum lines look like

The hashes are shortened here for the page; in a real file each line ends in a long base64 string. There are two lines per version: one for the module's files and one for its go.mod alone. You never read or edit these, you only commit them, and a mismatch is the toolchain telling you the download is not the code it expected.

Example · text
github.com/google/uuid v1.6.0 h1:<44 characters of base64>=
github.com/google/uuid v1.6.0/go.mod h1:<44 characters of base64>=

Day-to-day module commands

go mod tidy is the one to run before committing: it removes requirements nothing imports any more and fetches anything new you started importing. go list -m all is how you answer "which version of that library are we actually building against", including dependencies you never named yourself.

Example · bash
$ go mod init example.com/greet            # once, in an empty directory
$ go get github.com/google/[email protected]     # add a dependency at a chosen version
$ go mod tidy                              # match go.mod and go.sum to the imports in the code
$ go list -m all                           # every module this build uses, with versions

Discussion

  • Be the first to comment on this lesson.