go command provides all essential tools: build, run, test, and dependency managementCongratulations! You've completed the installation and setup chapter. You now have:
In the next chapter, we'll dive deep into Go's syntax and language features.
# Create project directory
mkdir my-project
cd my-project
# Initialize a module
go mod init my-project
This creates a go.mod file:
module my-project
go 1.23
Module path naming
The module path should typically match your repository URL:
# For a GitHub project
go mod init github.com/username/my-project
# For a local project
go mod init my-project
Adding dependencies
When you import a package in your code, Go automatically adds it to your dependencies:
package main
import (
"fmt"
"github.com/gin-gonic/gin" // External dependency
)
func main() {
r := gin.Default()
r.GET("/", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "Hello"})
})
r.Run()
}
Run go mod tidy to download dependencies:
go mod tidy
This will:
go.mod with dependenciesgo.sum with checksumsgo.mod file example
module my-project
go 1.23
require (
github.com/gin-gonic/gin v1.9.1
)
require (
github.com/bytedance/sonic v1.8.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
// ... more dependencies
)
Adding a specific version
go get github.com/gin-gonic/[email protected]
Updating dependencies
# Update all dependencies to latest versions
go get -u ./...
# Update a specific dependency
go get -u github.com/gin-gonic/gin
# Update to a specific version
go get github.com/gin-gonic/[email protected]
Removing unused dependencies
go mod tidy
This removes dependencies that are no longer imported.
go.mod file
The go.mod file is the source of truth for your module:
module github.com/user/project
go 1.23
require (
example.com/other v1.2.3
example.com/another v0.1.0
)
replace example.com/other => ../local/other
exclude example.com/bad v1.0.0
module: The module pathgo: Minimum Go version requiredrequire: Direct dependenciesreplace: Replace a dependency with a local path or different versionexclude: Exclude specific versionsgo.sum file
The go.sum file contains cryptographic checksums of dependencies:
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1S0lVI9J+0mg=
github.com/gin-gonic/gin v1.9.1/go.mod h1:jD2toBW3GJUr7m1owhpKJk7vMnXvXzH1+3U3uBx9r5c=
Important points
go.sum manuallygo.sum to version controlWhen working with Go modules, you may encounter situations where different dependencies require different versions of the same module. Understanding how Go resolves these conflicts is crucial for effective dependency management.
Version conflicts occur because in a complex dependency tree, different packages might require different versions of the same module. For example:
[email protected][email protected][email protected]Go must resolve this to a single version that satisfies all requirements.
Go resolves versions using an algorithm called Minimal Version Selection (MVS). This algorithm ensures reproducible builds by selecting the minimum version that satisfies all requirements.
MVS operates in the following steps:
go.mod files in the dependency treego.mod and go.sum files always produce the same dependency treeExample of version resolution
// Your go.mod
module myproject
go 1.23
require (
github.com/example/lib v1.2.0
github.com/other/pkg v1.0.0
)
// github.com/example/lib v1.2.0's go.mod requires:
// github.com/common/util v1.1.0
// github.com/other/pkg v1.0.0's go.mod requires:
// github.com/common/util v1.0.0
// Result: Go selects v1.1.0 (the minimum that satisfies both)
Viewing the resolved dependency tree
You can see which versions are actually used:
# List all dependencies with versions
go list -m all
# Show why a specific module is included
go mod why -m github.com/example/lib
# Show the dependency graph
go mod graph
Example output of go list -m all
myproject
github.com/example/lib v1.2.0
github.com/other/pkg v1.0.0
github.com/common/util v1.1.0 # Resolved to satisfy both dependencies
Handling version conflicts
If dependencies require incompatible versions (e.g., v1 and v2), Go treats them as different modules:
// These are treated as DIFFERENT modules:
github.com/example/lib v1.2.0
github.com/example/lib/v2 v2.0.0 // Different import path required
Major version changes
When a module releases a major version (v2, v3, etc.), the import path must change:
// v1 module
import "github.com/example/lib"
// v2 module (different import path)
import "github.com/example/lib/v2"
This allows both versions to coexist in the same project.
Practical example
# Initialize a project
go mod init example.com/myapp
# Add a dependency
go get github.com/gin-gonic/[email protected]
# Check what versions are actually used
go list -m all
# See the dependency graph
go mod graph | grep gin
Understanding indirect dependencies
Dependencies can be marked as indirect in go.mod:
require (
github.com/gin-gonic/gin v1.9.1 // Direct dependency
)
require (
github.com/bytedance/sonic v1.8.0 // indirect
// This is a dependency of gin, not directly imported by your code
)
Updating to resolve conflicts
If you need a newer version to satisfy all dependencies:
# Update all dependencies to latest compatible versions
go get -u ./...
# Update a specific dependency
go get -u github.com/example/lib
# Update to a specific version
go get github.com/example/[email protected]
Key points about version resolution
go.mod and go.sum produce the same dependency treeTroubleshooting version issues
# If you get version conflicts, check:
go mod why -m <module-name> # Why is this module included?
go list -m -versions <module-name> # What versions are available?
go mod tidy # Clean up and resolve dependencies
Vendoring dependencies
You can vendor dependencies (copy them into your project):
go mod vendor
This creates a vendor/ directory with all dependencies. Useful for:
Building with vendor
go build -mod=vendor
Module proxy
Go uses a module proxy by default (proxy.golang.org). You can configure it:
# Check proxy settings
go env GOPROXY
# Use direct mode (no proxy)
export GOPROXY=direct
# Use private proxy
export GOPROXY=https://proxy.company.com,direct
Private modules
For private repositories, configure authentication:
# Configure Git to use credentials
git config --global url."https://user:[email protected]/".insteadOf "https://github.com/"
# Or use GOPRIVATE
go env -w GOPRIVATE=github.com/company/*
Let's create a complete example:
# Create project
mkdir calculator
cd calculator
# Initialize module
go mod init github.com/user/calculator
# Create main.go
cat > main.go << 'EOF'
package main
import (
"fmt"
"github.com/user/calculator/math"
)
func main() {
result := math.Add(10, 5)
fmt.Printf("10 + 5 = %d\n", result)
}
EOF
# Create math package
mkdir math
cat > math/add.go << 'EOF'
package math
func Add(a, b int) int {
return a + b
}
EOF
# Build and run
go build
./calculator
Project structure
calculator/
go.mod
go.sum
main.go
math/
add.go
This demonstrates:
Congratulations! You've completed the installation and setup chapter. You now have:
In the next chapter, we'll dive deep into Go's syntax and language features.