Goal
In this quick lab, you will experience the most important Go Modules concepts:
import— use a package in Go source coderequire— record the module/version ingo.mod- Module cache — find where Go downloaded the dependency
go.sum— verify downloaded module content- Version management — inspect and pin a dependency version
replace— understand how a module can be redirected to another location- Essential Go module commands
Estimated time: 15 minutes
1. Check Go and Create the Module — 2 minutes
Check Go:
go version
Create the lab project:
mkdir go-modules-lab
cd go-modules-lab
go mod init example.com/go-modules-lab
Inspect the generated file:
cat go.mod
Example:
module example.com/go-modules-lab
go 1.24
Your Go version may be different.
What happened?
go mod init created go.mod, which identifies this project as a Go module.
2. Import an External Package — 3 minutes
Create main.go:
package main
import (
"fmt"
"github.com/google/uuid"
)
func main() {
id := uuid.New()
fmt.Println("Generated ID:", id)
}
Notice this line:
import "github.com/google/uuid"
An import appears in Go source code. It tells the compiler that this package is used by the program.
Now synchronize dependencies:
go mod tidy
Run the application:
go run .
Example output:
Generated ID: 550e8400-e29b-41d4-a716-446655440000
The UUID will be different each time.
3. See How import Becomes require — 2 minutes
Inspect go.mod:
cat go.mod
You should see an entry similar to:
module example.com/go-modules-lab
go 1.24
require github.com/google/uuid v1.6.0
Import vs. Require
| Item | Location | Meaning |
|---|---|---|
import | .go source file | This code uses a package |
require | go.mod | This module needs a particular module version |
In this example:
import "github.com/google/uuid"
causes Go tooling to record the providing module in go.mod:
require github.com/google/uuid v1.6.0
Usually, let Go commands such as go get and go mod tidy manage dependency requirements instead of manually editing versions.
4. Find Where Go Downloaded the Module — 2 minutes
Display the module cache location:
go env GOMODCACHE
A common location is similar to:
/home/student/go/pkg/mod
The default module cache is normally under:
$GOPATH/pkg/mod
Check your GOPATH:
go env GOPATH
Now ask Go for the exact directory of the downloaded UUID module:
go list -m -f '{{.Dir}}' github.com/google/uuid
Example:
/home/student/go/pkg/mod/github.com/google/uuid@v1.6.0
Important
Do not edit files inside the module cache. Go manages this directory.
To see how Go is configured to obtain modules, run:
go env GOPROXY
You may see something similar to:
https://proxy.golang.org,direct
The module may therefore be obtained through a configured Go module proxy or directly from its version-control source, depending on the environment and module settings.
5. Inspect go.sum and the Dependency Version — 2 minutes
Inspect the checksum file:
cat go.sum
You will see entries similar to:
github.com/google/uuid v1.6.0 h1:...
github.com/google/uuid v1.6.0/go.mod h1:...
go.sum records cryptographic hashes used by Go to verify module content.
Both go.mod and go.sum should normally be committed with your project.
See modules selected for the build:
go list -m all
See available versions of the UUID module:
go list -m -versions github.com/google/uuid
Pin or change to a specific version:
go get github.com/google/uuid@v1.6.0
Then synchronize:
go mod tidy
6. Understand replace — 2 minutes
A replace directive tells Go to use module code from another location instead of the normally resolved module source.
Example go.mod syntax:
require example.com/sharedlib v0.0.0
replace example.com/sharedlib => ../sharedlib
This is useful when developing two local modules together.
The application still imports the original module path:
import "example.com/sharedlib"
It does not change to:
import "../sharedlib"
You can create a replacement directive with:
go mod edit -replace=example.com/sharedlib=../sharedlib
View the result:
cat go.mod
Remove the demonstration directive afterward:
go mod edit -dropreplace=example.com/sharedlib
A
replacedirective redirects a module; it does not by itself make an unused module a dependency. The module must also be required somewhere in the module graph for the replacement to affect the build.
7. Essential Go Module Commands — 2 minutes
| Command | Purpose |
|---|---|
go mod init example.com/app | Create a new module |
go mod tidy | Add missing and remove unused requirements |
go get module@version | Add, upgrade, or downgrade a dependency |
go list -m all | List modules in the build list |
go list -m -versions module | Show known versions of a module |
go mod why -m module | Explain why a module is needed |
go mod graph | Show the module dependency graph |
go mod download | Download modules to the module cache |
go mod verify | Verify cached module content against recorded hashes |
go env GOMODCACHE | Show downloaded-module cache location |
go env GOPROXY | Show module download/proxy configuration |
go clean -modcache | Remove the entire downloaded module cache |
Try these three now:
go mod why -m github.com/google/uuid
go mod verify
go list -m all
Final Mental Model
main.go
|
| import "github.com/google/uuid"
v
go mod tidy / go get
|
+----> go.mod
| require github.com/google/uuid v1.6.0
|
+----> go.sum
| dependency checksums
|
+----> GOMODCACHE
downloaded module source
With a replacement:
import example.com/sharedlib
|
v
require example.com/sharedlib ...
|
v
replace example.com/sharedlib => ../sharedlib
|
v
local module source
Final Check
Your project should contain:
go-modules-lab/
├── go.mod
├── go.sum
└── main.go
Run:
go mod tidy
go mod verify
go run .
If the application runs successfully, the lab is complete.
What You Experienced
You now understand the core dependency flow:
IMPORT -> package used by source code
REQUIRE -> module/version recorded in go.mod
DOWNLOAD -> module stored in GOMODCACHE
GO.SUM -> verifies downloaded content
REPLACE -> redirects a module to another source/location
Lab complete.