3. Modules

Go programs are organized into packages. A package is a directory of Go code that's all compiled together. Functions, types, variables, and constants defined in one source file are visible to all other source files within the same package (directory).

A repository contains one or more modules. A module is a collection of Go packages that are released together.

Go modules illustration

One Module Per Repo (Usually)

A file named go.mod at the root of a project declares the module. It contains:

  • The module path

  • The version of the Go language your project requires

  • Optionally, any external package dependencies your project has

The module path is just the import path prefix for all packages within the module. Here's an example of a go.mod file:

Each module's path not only serves as an import path prefix for the packages within but also indicates where the go command should look to download it. For example, to download the module golang.org/x/tools, the go command would consult the repository located at https://golang.org/x/tools.

An "import path" is a string used to import a package. A package's import path is its module path joined with its subdirectory within the module. For example, the module github.com/google/go-cmp contains a package in the directory cmp/. That package's import path is github.com/google/go-cmp/cmp. Packages in the standard library do not have a module path prefix.

-- Paraphrased from Golang.org's code organization (https://golang.org/doc/code#Organization)

Only GitHub?

You don't need to publish your code to a remote repository before you can build it. A module can be defined locally without belonging to a remote repository. However, it's a good habit to keep a copy of all your projects on some remote server, like GitHub.

Package vs Module vs Repository

Package

  • A directory of Go code

  • All .go files in the same directory = same package

  • Files in the same package can see each other's functions, types, variables

Module

  • A collection of packages released together

  • Defined by a go.mod file at the root

  • Usually one module per repository

Repository

  • The GitHub/GitLab repo

  • Contains one or more modules (usually just one)

The go.mod File

Located at the root of your project:

What's in it:

1

Module path

github.com/bootdotdev/exampleproject

2

Go version

go 1.25.1

3

Dependencies

require github.com/google/examplepackage v1.3.0

Module Path

The module path serves two purposes:

1

Import path prefix

Used as the import path prefix for all packages in the module.

2

Download location

Tells the go command where to look to download the module.

Example:

Tells Go to look at https://github.com/myname/myproject to download this module.

Package Import Paths

Formula:

Example structure:

Import path:

Same Package = Can See Everything

All files in the same package (directory) can access each other's code:

helpers.go:

main.go:

Standard Library Exception

Standard library packages don't have a module path prefix:

Example Project Structure

go.mod:

Importing packages:

Local vs Remote

You don't need GitHub to build:

This works locally, but can't be downloaded by others.

But it's good practice to use a full path:

Even if not published yet, this prepares for future publishing.

Key Takeaways

  • Package = directory of .go files compiled together

  • Module = collection of packages, defined by go.mod

  • One module per repo is the standard

  • Module path = import prefix + download location

  • Same package = all code visible to each other

  • go.mod declares module path, Go version, dependencies

Visual Summary