Skip to main content
โšก Calmops

Go Modules: Dependency Management

Go Modules: Dependency Management

Go modules revolutionized dependency management in Go. Before Go 1.11, managing dependencies was challenging and error-prone. Modules provide a clean, reproducible way to manage project dependencies with semantic versioning. This guide covers everything you need to master Go modules.

Understanding Go Modules

A Go module is a collection of Go packages stored in a file tree with a go.mod file at its root. The go.mod file defines the module’s identity and its dependency requirements.

What is go.mod?

The go.mod file specifies:

  • The module name (import path)
  • The Go version
  • Required dependencies and their versions
  • Indirect dependencies

Example go.mod:

module github.com/username/myapp

go 1.21

require (
    github.com/gin-gonic/gin v1.9.1
    github.com/lib/pq v1.10.9
)

require (
    github.com/google/uuid v1.3.0 // indirect
)

What is go.sum?

The go.sum file contains cryptographic hashes of module versions. It ensures that dependencies haven’t been tampered with and provides reproducible builds.

github.com/gin-gonic/gin v1.9.1 h1:...
github.com/gin-gonic/gin v1.9.1/go.mod h1:...
github.com/lib/pq v1.10.9 h1:...
github.com/lib/pq v1.10.9/go.mod h1:...

Initializing a Module

Creating a New Module

mkdir myapp
cd myapp
go mod init github.com/username/myapp

This creates a go.mod file:

module github.com/username/myapp

go 1.21

Module Naming Conventions

Module names should follow the pattern:

domain/username/projectname

Examples:

  • github.com/golang/go - Official Go repository
  • github.com/sirupsen/logrus - Popular logging library
  • gitlab.com/mycompany/internal-tool - Internal tool
  • example.com/myteam/service - Company service

For private modules, use your domain or company domain.

Adding Dependencies

Adding a Dependency

go get github.com/gin-gonic/gin

This:

  1. Downloads the latest version
  2. Updates go.mod with the requirement
  3. Updates go.sum with hashes
  4. Makes the package available for import

Specifying Versions

# Latest version
go get github.com/gin-gonic/gin

# Specific version
go get github.com/gin-gonic/[email protected]

# Latest patch version
go get github.com/gin-gonic/[email protected]

# Latest minor version
go get github.com/gin-gonic/gin@v1

# Latest pre-release
go get github.com/gin-gonic/gin@latest

# Specific commit
go get github.com/gin-gonic/gin@abc123def456

# Branch
go get github.com/gin-gonic/gin@main

Updating Dependencies

# Update all dependencies to latest patch versions
go get -u ./...

# Update all dependencies to latest minor/major versions
go get -u -t ./...

# Update specific dependency
go get -u github.com/gin-gonic/gin

# Update to specific version
go get github.com/gin-gonic/[email protected]

Semantic Versioning

Go modules use semantic versioning: MAJOR.MINOR.PATCH

  • MAJOR: Breaking changes
  • MINOR: New features (backward compatible)
  • PATCH: Bug fixes (backward compatible)

Examples:

  • v1.0.0 โ†’ v1.0.1 - Patch release
  • v1.0.0 โ†’ v1.1.0 - Minor release
  • v1.0.0 โ†’ v2.0.0 - Major release

Version Constraints

In go.mod, you can specify version constraints:

require (
    github.com/gin-gonic/gin v1.9.1      // Exact version
    github.com/lib/pq >= v1.10.0          // Minimum version
    github.com/google/uuid < v2.0.0       // Maximum version
    github.com/sirupsen/logrus >= v1.8.0, < v2.0.0  // Range
)

Managing go.mod and go.sum

Tidying Dependencies

# Remove unused dependencies and add missing ones
go mod tidy

This is the most important command. Run it regularly to keep your module clean.

Downloading Dependencies

# Download all dependencies
go mod download

# Download specific dependency
go mod download github.com/gin-gonic/[email protected]

Verifying Dependencies

# Verify all dependencies
go mod verify

# Check for security vulnerabilities
go list -json -m all | nancy sleuth

Viewing Dependency Graph

# Show all dependencies
go mod graph

# Show dependencies in tree format
go mod graph | head -20

# Using go list
go list -m all

Working with Private Modules

Configuring Git Credentials

For private repositories on GitHub:

# Configure git to use SSH
git config --global url."[email protected]:".insteadOf "https://github.com/"

# Or use personal access token
git config --global url."https://USERNAME:[email protected]/".insteadOf "https://github.com/"

Using Private Modules

# Add private module
go get github.com/mycompany/private-lib

# In go.mod
require github.com/mycompany/private-lib v1.0.0

GOPRIVATE Configuration

# Mark modules as private (skip proxy)
export GOPRIVATE=github.com/mycompany/*

# Or in go.env
go env -w GOPRIVATE=github.com/mycompany/*

Module Proxies and Checksums

Using a Module Proxy

# Use official Go proxy (default)
export GOPROXY=https://proxy.golang.org

# Use multiple proxies
export GOPROXY=https://proxy.company.com,https://proxy.golang.org

# Disable proxy (use direct)
export GOPROXY=direct

# Use local proxy
export GOPROXY=file:///path/to/local/proxy

Checksum Database

# Use official checksum database (default)
export GOSUMDB=sum.golang.org

# Disable checksum verification
export GOSUMDB=off

# Use custom checksum database
export GOSUMDB=sum.company.com

Common Module Operations

Replacing Dependencies

Sometimes you need to use a different version or fork:

# In go.mod
replace github.com/gin-gonic/gin => github.com/mycompany/gin v1.9.1

# Or use local path
replace github.com/gin-gonic/gin => ../local-gin

Excluding Versions

# In go.mod
exclude github.com/gin-gonic/gin v1.8.0

Retraction

If you publish a bad version, retract it:

// In go.mod
retract v1.0.0
retract [v1.0.0, v1.0.5]

Best Practices

โœ… Good Practices

  1. Commit go.mod and go.sum - Always commit both files to version control
  2. Run go mod tidy regularly - Keep dependencies clean
  3. Use specific versions - Avoid latest in production
  4. Review dependency updates - Check changelogs before updating
  5. Use semantic versioning - Follow MAJOR.MINOR.PATCH
  6. Document dependencies - Include rationale for major dependencies
  7. Keep dependencies minimal - Only add what you need
  8. Update regularly - Stay current with security patches

โŒ Anti-Patterns

// โŒ Bad: Committing vendor directory (usually)
// Only commit if you need offline builds

// โŒ Bad: Using latest in production
require github.com/gin-gonic/gin latest

// โŒ Bad: Ignoring go.sum
// Always commit go.sum for reproducibility

// โŒ Bad: Not running go mod tidy
// Leaves unused dependencies

// โŒ Bad: Using replace in published modules
// Only use replace for local development

// โŒ Bad: Circular dependencies
// Restructure to eliminate cycles

Troubleshooting

Module Not Found

# Problem: "cannot find module"
# Solution 1: Ensure module is public or credentials are configured
go get github.com/username/module

# Solution 2: Check GOPRIVATE
export GOPRIVATE=github.com/mycompany/*

# Solution 3: Use direct download
export GOPROXY=direct
go get github.com/username/module

Version Conflicts

# Problem: "conflicting requirements"
# Solution: Use go mod tidy to resolve
go mod tidy

# Or manually edit go.mod to compatible versions

Checksum Mismatch

# Problem: "checksum mismatch"
# Solution 1: Clear cache and re-download
go clean -modcache
go mod download

# Solution 2: Disable checksum verification (not recommended)
export GOSUMDB=off

Vendoring

For offline builds or reproducibility:

# Create vendor directory
go mod vendor

# Use vendor directory
go build -mod=vendor

# Commit vendor directory
git add vendor/
git commit -m "Add vendor dependencies"

Advanced Module Features

Module Directives

// In go.mod

// Specify Go version
go 1.21

// Require specific versions
require github.com/gin-gonic/gin v1.9.1

// Indirect dependencies (managed automatically)
require github.com/google/uuid v1.3.0 // indirect

// Replace with local path
replace github.com/gin-gonic/gin => ../local-gin

// Replace with different version
replace github.com/gin-gonic/gin => github.com/mycompany/gin v1.9.1

// Exclude versions
exclude github.com/gin-gonic/gin v1.8.0

// Retract versions
retract v1.0.0

Workspace Mode

For working with multiple modules:

# Create go.work
go work init ./module1 ./module2 ./module3

# Add modules
go work use ./module4

# Remove modules
go work edit -dropuse=./module4

Resources and References

Official Documentation

Tools and Resources

Summary

Go modules provide a robust, reproducible way to manage dependencies:

  • Initialize with go mod init
  • Add dependencies with go get
  • Keep dependencies clean with go mod tidy
  • Always commit go.mod and go.sum
  • Use semantic versioning
  • Review updates before applying
  • Use go mod vendor for offline builds

Mastering modules is essential for professional Go development.

Comments