最早的时候,Go 所依赖的所有第三方库都放在 GOPATH 目录下。随着 Go 语言的发展,从 v1.5 开始引入 vendor 模式。本文介绍两个 Golang 官方依赖管理工具。
依赖管理演进
┌─────────────────────────────────────────────────────────────┐
│ Go 依赖管理演进 │
├─────────────────────────────────────────────────────────────┤
│ │
│ GOPATH 时代 ──▶ Vendor 时代 ──▶ dep 时代 ──▶ go mod 时代 │
│ (2012) (2014) (2017) (2018) │
│ │
└─────────────────────────────────────────────────────────────┘
dep(已过时)
⚠️ 提示:dep 已停止维护,建议使用 go modules。
安装
# macOS
brew install dep
# Linux
curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
# Windows
go get -u github.com/golang/dep/cmd/dep
常用命令
| 命令 | 说明 |
|---|
dep init | 初始化项目,生成 Gopkg.toml 和 Gopkg.lock |
dep status | 查看依赖状态 |
dep ensure | 确保依赖已安装 |
dep ensure -add | 添加新依赖 |
dep ensure -update | 更新依赖版本 |
dep check | 检查导入是否同步 |
使用示例
# 初始化项目
dep init
# 添加依赖
dep ensure -add github.com/spf13/viper
# 更新所有依赖
dep ensure -update
# 查看状态
dep status
配置文件
# Gopkg.toml
[[constraint]]
name = "github.com/spf13/viper"
version = "^1.6.0"
[[constraint]]
name = "github.com/go-sql-driver/mysql"
version = "^1.5.0"
go modules(推荐)
go modules 是 Go 1.11 引入的官方依赖管理方案,现在已是主流。
核心概念
| 概念 | 说明 |
|---|
| Module | 相关 Go 包的集合,是版本控制的单元 |
| go.mod | 模块定义文件,记录依赖关系 |
| go.sum | 依赖校验文件,确保构建一致性 |
| GOPROXY | 依赖代理服务器,加速下载 |
启用方式
# Go 1.11+ 默认启用
export GO111MODULE=on # 显式启用
export GO111MODULE=off # 禁用(使用 GOPATH)
export GO111MODULE=auto # 自动检测(默认)
常用命令
| 命令 | 说明 |
|---|
go mod init | 初始化模块,生成 go.mod |
go mod tidy | 整理依赖(添加缺失,移除未用) |
go mod download | 下载依赖到本地缓存 |
go mod vendor | 将依赖复制到 vendor 目录 |
go mod graph | 打印依赖图 |
go mod verify | 验证依赖是否正确 |
go mod why | 解释为什么需要某依赖 |
初始化项目
# 在项目目录执行
go mod init github.com/username/project
# 或指定模块名
go mod init mymodule
go.mod 示例
module github.com/username/project
go 1.21
require (
github.com/gin-gonic/gin v1.9.1
github.com/go-sql-driver/mysql v1.7.1
github.com/spf13/viper v1.16.0
)
require (
github.com/bytedance/sonic v1.9.1 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
)
go.sum 示例
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YIdfeAwnHoK0S2RThAQPz7AH81q6Us=
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
完整使用流程
1. 创建新项目
# 创建项目目录
mkdir myproject && cd myproject
# 初始化模块
go mod init github.com/username/myproject
# 创建主文件
cat > main.go << 'EOF'
package main
import (
"fmt"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "pong"})
})
r.Run()
}
EOF
# 下载依赖并整理
go mod tidy
2. 添加依赖
# 方式一:go get
go get github.com/spf13/viper
# 指定版本
go get github.com/spf13/viper@v1.16.0
# 最新版本
go get github.com/spf13/viper@latest
# 指定分支
go get github.com/spf13/viper@master
# 指定 commit
go get github.com/spf13/viper@e3861e3
# 方式二:直接编辑 go.mod
echo 'github.com/redis/go-redis/v9 v9.0.0' >> go.mod
go mod tidy
3. 升级/降级依赖
# 升级到最新版本
go get -u github.com/gin-gonic/gin
# 升级到指定版本
go get github.com/gin-gonic/gin@v1.9.0
# 清理未使用的依赖
go mod tidy
4. 使用 vendor
# 将依赖复制到 vendor 目录
go mod vendor
# 查看 vendor 内容
ls vendor/
# 使用 vendor 构建
go build -mod=vendor
代理配置
设置 GOPROXY
# 阿里云代理(推荐国内使用)
go env -w GOPROXY=https://mirrors.aliyun.com/goproxy/,direct
# 官方代理
go env -w GOPROXY=https://proxy.golang.org,direct
# 七牛云
go env -w GOPROXY=https://goproxy.cn,direct
# 多个代理(逗号分隔)
go env -w GOPROXY=https://goproxy.cn,https://proxy.golang.org,direct
代理参数
| 参数 | 说明 |
|---|
direct | 直连源站 |
off | 禁用代理 |
=https://proxy.golang.org | 官方代理 |
私有模块
设置 GONOSUMDB
# 跳过校验的域名
go env -w GONOSUMDB="gitlab.com/mycompany/*"
设置 GOPRIVATE
# 私有模块不走代理
go env -w GOPRIVATE="gitlab.com/mycompany,github.com/myteam"
配置 netrc
# ~/.netrc
machine github.com
login your-username
password your-token
常见问题
Q: 依赖下载失败
# 清理缓存
go clean -modcache
# 设置国内镜像
go env -w GOPROXY=https://goproxy.cn,direct
Q: go.mod 和 go.sum 不同步
Q: vendor 和 mod 冲突
# 删除 vendor,使用 go mod
rm -rf vendor
go mod tidy
Q: 循环导入
# 检查依赖图
go mod graph | grep ":"
最佳实践
- 始终使用 go mod tidy 保持依赖整洁
- 使用 vendor 确保构建可重复
- 使用国内镜像 加速下载
- 定期升级依赖 获取安全补丁
- 提交
go.sum 锁校验和到版本库,CI 使用 go mod verify 防止依赖被篡改。
延伸阅读