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 repositorygithub.com/sirupsen/logrus- Popular logging librarygitlab.com/mycompany/internal-tool- Internal toolexample.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:
- Downloads the latest version
- Updates
go.modwith the requirement - Updates
go.sumwith hashes - 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 releasev1.0.0โv1.1.0- Minor releasev1.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
- Commit go.mod and go.sum - Always commit both files to version control
- Run go mod tidy regularly - Keep dependencies clean
- Use specific versions - Avoid
latestin production - Review dependency updates - Check changelogs before updating
- Use semantic versioning - Follow MAJOR.MINOR.PATCH
- Document dependencies - Include rationale for major dependencies
- Keep dependencies minimal - Only add what you need
- 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
- Go Modules Documentation - Complete modules reference
- Go Module Proxy - Official module proxy
- Go Checksum Database - Official checksum database
Recommended Reading
- Using Go Modules - Official blog post
- Go Modules by Example - Practical examples
- Semantic Versioning - Version numbering guide
Tools and Resources
- pkg.go.dev - Go package documentation
- Go Module Tidy - Official documentation
- Dependency Management Best Practices - Community guide
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.modandgo.sum - Use semantic versioning
- Review updates before applying
- Use
go mod vendorfor offline builds
Mastering modules is essential for professional Go development.
Comments