第 8 章 · 包管理与 go mod
本章目标:掌握 go mod init/get/tidy/vendor、语义化版本 semver、go.sum 校验;理解 internal/ 与 pkg/ 可见性规则;使用 replace 本地调试;为 toolkit-go 引入 uuid 等依赖并组织多包结构;对照 java-dev Maven 与 python-dev pip。
学时建议:3~4 小时(含 1 小时跟练)
前置:完成 go-dev ch07;建议已学 java-dev ch01 Maven 章节。
8.1 场景说明:模块化 toolkit-go
从本章起,toolkit-go(~/learn-go/toolkit-go,模块 example.com/toolkit-go)将拆分多个包并引入第三方库(如 github.com/google/uuid 生成请求 ID,与 gin-web 中间件概念呼应)。
toolkit-go/
├── go.mod
├── go.sum
├── cmd/
│ └── toolkit/
│ └── main.go
├── internal/
│ ├── model/
│ ├── logparser/
│ └── report/
└── pkg/
└── id/
└── id.go
| Maven(java-dev) | go mod(go-dev) | pip(python-dev) |
|---|---|---|
pom.xml | go.mod | requirements.txt / pyproject.toml |
groupId:artifactId:version | 模块路径 @v1.2.3 | package==1.2.3 |
mvn install | go install | pip install |
~/.m2/repository | $GOMODCACHE | site-packages |
| 多模块 parent pom | go work(选修) | monorepo 工具 |
8.2 go.mod 基础
8.2.1 初始化
| 步骤 | 操作(Windows) | 说明 |
|---|---|---|
| 1 | cd %USERPROFILE%\learn-go\toolkit-go | 项目根 |
| 2 | go mod init example.com/toolkit-go | 若 ch01 已 init 可跳过 |
| 3 | 查看 go.mod | 确认 module 行 |
| 步骤 | 操作(macOS / Linux) | 说明 |
|---|---|---|
| 1 | cd ~/learn-go/toolkit-go | 项目根 |
| 2 | go mod init example.com/toolkit-go | 同上 |
go.mod 示例:
module example.com/toolkit-go
go 1.22
8.2.2 常用指令
| 指令 | 作用 | Maven 对照 |
|---|---|---|
go mod init MODULE | 创建 go.mod | 创建 pom.xml |
go get pkg@v1.2.3 | 添加/升级依赖 | 添加 dependency |
go mod tidy | 增删 require,同步 go.sum | 依赖解析 |
go mod verify | 校验 go.sum | 完整性检查 |
go list -m all | 列出模块版本 | dependency tree |
go mod graph | 依赖图 | mvn dependency:tree |
go build ./... | 编译全模块 | mvn compile |
go test ./... | 测试全模块 | mvn test |
8.3 引入依赖与版本选择
# Windows
cd $env:USERPROFILE\learn-go\toolkit-go
go get github.com/google/uuid@v1.6.0
go get github.com/stretchr/testify@v1.9.0
go mod tidy
# macOS / Linux
cd ~/learn-go/toolkit-go
go get github.com/google/uuid@v1.6.0
go get github.com/stretchr/testify@v1.9.0
go mod tidy
更新后 go.mod:
module example.com/toolkit-go
go 1.22
require (
github.com/google/uuid v1.6.0
github.com/stretchr/testify v1.9.0
)
语义化版本 semver:
| 版本写法 | 含义 |
|---|---|
v1.6.0 | 精确版本 |
v1.6 | 不低于 v1.6.0 的最新 v1.6.x |
@latest | 最新版(教学慎用) |
v0.x.y | 不稳定 API,可 breaking change |
v2+ | 模块路径常需 /v2 后缀 |
Go 使用 Minimal Version Selection (MVS):选择满足所有 require 的最低兼容版本。
8.4 go.sum 的作用
go.sum 记录每个模块版本的加密哈希,保证可重现构建。
github.com/google/uuid v1.6.0 h1:xxx...
github.com/google/uuid v1.6.0/go.mod h1:yyy...
| 问题 | 处理 |
|---|---|
go.sum mismatch | 运行 go mod tidy |
| 误删 go.sum | go mod tidy 重建 |
| CI 校验 | go mod verify |
| 是否提交 git | 是,与 go.mod 一起提交 |
对照 Maven:go.sum 类似 lock file;Maven 依赖 jar 也有校验机制。
8.5 pkg/id:封装 uuid
// pkg/id/id.go
package id
import "github.com/google/uuid"
// NewRequestID 生成请求追踪 ID(教学用)
func NewRequestID() string {
return uuid.NewString()
}
// pkg/id/id_test.go — ch13 会扩展测试
package id
import "testing"
func TestNewRequestID(t *testing.T) {
a := NewRequestID()
b := NewRequestID()
if a == b {
t.Fatal("uuid should differ")
}
if len(a) != 36 {
t.Fatalf("unexpected len %d", len(a))
}
}
pkg vs internal:pkg/id 可被外部项目 import;internal/* 仅本模块内可 import。
8.6 internal 与可见性
| 目录/规则 | import 规则 |
|---|---|
internal/xxx | 仅 example.com/toolkit-go 模块内可 import |
pkg/xxx | 外部项目可引用(谨慎公开) |
| 小写标识符 | 包内私有 |
| 大写标识符 | 导出 |
// cmd/toolkit/main.go
package main
import (
"fmt"
"example.com/toolkit-go/internal/report"
"example.com/toolkit-go/pkg/id"
)
func main() {
fmt.Println("RequestID:", id.NewRequestID())
_ = report.CSVReporter{}
fmt.Println("toolkit-go module ready")
}
外部模块尝试 import "example.com/toolkit-go/internal/report" → 编译失败(编译器强制)。
8.7 replace 与 go work(本地联调)
多模块开发或 fork 调试时:
// go.mod 片段
replace example.com/api-go-demo => ../api-go-demo
# Go 1.18+ workspace(选修)
go work init .
go work use ../api-go-demo
与 gin-web api-go-demo 同目录 learn-go/ 便于切换:
learn-go/
├── toolkit-go/
└── api-go-demo/ # gin-web 练习
| 场景 | 方案 |
|---|---|
| 本地联调依赖 | replace |
| 多模块同时开发 | go work |
| 发布到生产 | 去掉 replace,用真实版本 |
8.8 构建、安装与交叉编译
Windows:
cd $env:USERPROFILE\learn-go\toolkit-go
go build -o bin\toolkit.exe ./cmd/toolkit
go install ./cmd/toolkit
$env:GOOS="linux"
$env:GOARCH="amd64"
go build -o bin\toolkit-linux ./cmd/toolkit