包与模块

翻译整理自 Go Modules Reference 与 Tutorial: Create a module。

1. 什么是模块

Module 是 Go 的依赖管理单位,由 go.mod 文件描述:

  • 一组相关包的集合
  • 唯一的模块路径(如 github.com/me/mylib)
  • 依赖列表与版本

一个 module 可以包含多个 package(每个目录一个 package)。

2. 初始化模块

mkdir greetings && cd greetings
go mod init github.com/me/greetings

生成的 go.mod:

module github.com/me/greetings

go 1.23

3. 包的定义与可见性

每个目录一个包,包名通常与目录同名(最后一段)。例如 github.com/me/greetings 内的文件:

package greetings

// 首字母大写 = 可被外部包引用(导出)
func Hello(name string) string {
    return "Hello, " + name
}

// 首字母小写 = 仅包内可见
func helper() string { return "..." }

4. 调用本地模块

新建另一个 module:

mkdir hello && cd hello
go mod init github.com/me/hello

编辑 go.mod 引用本地 greetings:

replace github.com/me/greetings => ../greetings
require github.com/me/greetings v0.0.0-00010101000000-000000000000

代码中使用:

package main

import (
    "fmt"
    "github.com/me/greetings"
)

func main() {
    fmt.Println(greetings.Hello("Go"))
}

同步依赖:

go mod tidy

5. 工作区 Workspace(Go 1.18+)

需要在多个本地 module 同时开发时,用工作区:

mkdir workspace && cd workspace
go work init ./greetings ./hello

生成 go.work:

go 1.23
use ./greetings
use ./hello

工作区让 go run / go build 优先使用本地路径而不是 go.mod 中的版本。

6. 添加与升级依赖

go get golang.org/x/tools@latest     # 最新
go get golang.org/x/[email protected]    # 指定版本
go get golang.org/x/tools@main       # 跟踪分支
go get -u golang.org/x/tools         # 升级到最新次要版本
go mod tidy                          # 清理无用依赖

7. 模块版本与 SemVer

Go 模块遵循 SemVer:

v1.2.3
│ │ └── 修补版本(兼容)
│ └── 次要版本(同主版本兼容)
└── 主版本(可能不兼容)

主版本 ≥ 2 时,模块路径要加 /v2 后缀(如 github.com/x/foo/v2)。

8. 发布模块

1. 给 git 仓库打 tag:git tag v1.0.0
2. 推送:git push --tags
3. 设置 GOPROXY 让 pkg.go.dev 收录

pkg.go.dev 会自动抓取,配合 go get 让他人引用。

9. 标准库常用包速查

包 用途
fmt 格式化 IO
strings / bytes 字符串、字节切片操作
strconv 字符串与数值互转
errors 错误处理
io / io/fs IO 抽象
os 操作系统接口
time 时间
net/http HTTP 服务端、客户端
encoding/json JSON 编解码
context 取消、超时
sync 并发原语
testing 测试
log 日志

小结

模块、包、工作区是 Go 工程化的根基。掌握后,你可以发布自己的库、与他人协作。下一章学习测试。