gestion-dependencias-go-mod-sum

Modules in Go: go.mod, go.sum, and Dependency Management

  • 5 min

A Go module is the unit that groups a project and its dependencies. In practice, it’s the starting point for compiling, versioning, and sharing modern Go code.

For many years, dependency management in Go was… complicated. There was an environment variable called GOPATH that forced you to keep all your code in a specific system folder. It was rigid and painful.

Go introduced modules in version 1.11, and since Go 1.16, module mode is enabled by default.

It no longer matters where we save our code. The module definition revolves around go.mod, and when there are downloaded dependencies, go.sum records the necessary checksums to verify them.

Let’s see what each file contains and how to maintain them with Go’s tools.

The go.mod File

The go.mod file is the heart of your project. It defines who you are and what you need.

When you run go mod init project-name, this file is created. Let’s see a real example:

// 1. Module name (usually a repo URL)
module github.com/luisllamas/mi-api

// 2. Minimum required Go version
go 1.25.0

// 3. List of direct and indirect dependencies
require (
    github.com/gin-gonic/gin v1.9.1
    github.com/google/uuid v1.3.0
    golang.org/x/sys v0.8.0 // indirect
)
Copied!

Anatomy

  • module: This is the unique identifier. If you’re uploading your code to GitHub, it must match the URL (github.com/user/repo). This allows others to import your code using it.
  • go: the minimum required Go version and the language semantics used by the module. As of Go 1.21, an older tool will reject a module that requires a newer version.
  • require: declares minimum versions of other modules. Go resolves the final set through Minimal Version Selection.

Do you see that // indirect comment? It means you haven’t imported that library directly, but one of your dependencies needs it to function. Go manages it for you.

The go.sum File: Checksums

This part often causes confusion. If you come from Node.js, you might think go.sum is like package-lock.json. It partly is, but its main function is Cryptographic Integrity.

The go.sum file is not a lock file or a dependency tree. It contains checksums of module content and their go.mod files that the tools have needed to download.

github.com/gin-gonic/gin v1.9.1 h1:4... (hash)
github.com/gin-gonic/gin v1.9.1/go.mod h1:h... (hash)
Copied!

What is it for? Imagine you download the library uuid v1.3.0 today. Tomorrow, a hacker (or a malicious maintainer) changes the code of version v1.3.0 on GitHub to inject a virus, but keeps the same version number.

When your colleagues (or the CI/CD server) try to download that version, Go will compare the hash of what they download with what your go.sum says. If they don’t match, Go will block the download and raise a security alert.

The go.sum file should be uploaded to the repository. Along with go.mod, it allows verifying that the downloaded content matches what the project knows. It can retain entries for versions no longer in the build list, and go mod tidy will remove unnecessary ones.

Daily Workflow

In day-to-day work, you’ll barely touch these files manually. You’ll use the Go CLI commands.

Adding a Dependency with go get

If you want to use an external library, like the web framework “Fiber”:

go get github.com/gofiber/fiber/v2@latest
Copied!

This updates go.mod with a version that contains the requested package. The tools will download the necessary modules to the cache and update go.sum.

The -u option also attempts to update direct or indirect dependencies of the specified package. Don’t add it out of habit if you only want to incorporate a specific library; always review the changes to go.mod and go.sum.

Importing the Package in Code

Once downloaded, you use it in your .go file:

import "github.com/gofiber/fiber/v2"
Copied!

Adjusting the Module with go mod tidy

This is the command you’ll use constantly. As you code, you sometimes delete an import because you stop using a library, or you add a new one manually. The go.mod file can become “dirty” (with dependencies you no longer use or missing ones).

The go mod tidy command does general cleanup:

  1. Adds any missing dependencies.
  2. Removes dependencies you no longer use in your code.
  3. Updates go.sum.

Run go mod tidy after changing imports and review its diff before committing the changes.

Semantic Versioning and Updates

Go takes Semantic Versioning (Major.Minor.Patch) very seriously.

  • v1.0.0 to v1.9.9: they share the same module path. Semantic versioning promises compatibility, but an update still deserves testing and review.
  • v2.0.0 (Major Upgrade): This is where things change.

If a library releases version v2, Go considers it a different library with a different import path.

// Version 1
import "github.com/user/my-lib"

// Version 2 (Breaks compatibility)
import "github.com/user/my-lib/v2"
Copied!

The different paths allow v1 and v2 to coexist in the same dependency graph if two parts of the program need them.

Where is the dependencies folder?

Go stores dependencies in a shared cache indicated by GOMODCACHE (by default, $GOPATH/pkg/mod).

This has two significant advantages:

  1. Disk savings: multiple projects can reuse the same downloaded version of a module.
  2. Speed: if a version is already in the cache, it doesn’t need to be downloaded again.