模块代理是一个 HTTP 服务器,用于响应 Go 工具的模块请求。使用代理可以:
# 设置代理
go env -w GOPROXY=https://goproxy.cn,direct
# 多个代理(按顺序尝试)
go env -w GOPROXY=https://goproxy.cn,https://proxy.golang.org,direct
# 查看当前配置
go env GOPROXY
| 代理地址 | 说明 |
|---|---|
| https://goproxy.cn | 七牛云代理(国内推荐) |
| https://goproxy.io | 社区维护的代理 |
| https://proxy.golang.org | Go 官方代理 |
| direct | 直接从源下载 |
# 完整配置
go env -w GOPROXY=https://goproxy.cn,direct
go env -w GOSUMDB=sum.golang.org
go env -w GOPRIVATE=github.com/myorg/*
# 查看所有配置
go env
校验和数据库,用于验证下载的模块:
# 使用默认校验和数据库
go env -w GOSUMDB=sum.golang.org
# 使用国内镜像
go env -w GOSUMDB=sum.golang.google.cn
# 关闭校验(不推荐)
go env -w GOSUMDB=off
Go 使用最小版本选择算法:
// go.mod
module example.com/myapp
go 1.21
require (
example.com/A v1.2.0
example.com/B v1.3.0
)
如果 A 需要 C v1.1.0,B 需要 C v1.2.0:
module example.com/myapp
go 1.21
require (
github.com/gin-gonic/gin v1.9.1
gorm.io/gorm v1.25.5 // indirect
)
// indirect 注释表示这是间接依赖。
# 查看依赖图
go mod graph
# 输出示例
github.com/example/myapp github.com/gin-gonic/gin@v1.9.1
github.com/gin-gonic/gin@v1.9.1 github.com/golang/protobuf@v1.5.3
github.com/gin-gonic/gin@v1.9.1 golang.org/x/crypto@v0.11.0
...
当不同模块需要同一依赖的不同版本时:
module example.com/myapp
go 1.21
require (
example.com/A v1.0.0 // 需要 C v1.0.0
example.com/B v1.0.0 // 需要 C v2.0.0
)
# 升级所有依赖
go get -u ./...
go mod tidy
module example.com/myapp
go 1.21
require (
example.com/A v1.0.0
example.com/B v1.0.0
)
replace example.com/C => example.com/C v2.0.0
module example.com/myapp
go 1.21
require (
example.com/A v1.0.0
example.com/B v1.0.0
)
exclude example.com/C v1.0.0
在 Go Modules 中,主版本 v2+ 需要使用不同的模块路径:
// v1.x.x
module github.com/example/pkg
// v2.x.x
module github.com/example/pkg/v2
// v3.x.x
module github.com/example/pkg/v3
module example.com/myapp
go 1.21
require (
github.com/example/pkg v1.2.0
github.com/example/pkg/v2 v2.0.0
github.com/example/pkg/v3 v3.0.0
)
# 创建 v2 分支
git checkout -b v2
# 修改 go.mod
echo 'module github.com/example/pkg/v2' > go.mod
# 提交并打标签
git add go.mod
git commit -m "prepare v2"
git tag v2.0.0
git push origin v2 --tags
查看完整的依赖图:
go mod graph | head -20
查看为什么需要某个依赖:
go mod why github.com/golang/protobuf
输出:
# github.com/golang/protobuf
github.com/example/myapp
github.com/gin-gonic/gin
github.com/gin-gonic/gin/binding
github.com/golang/protobuf/proto
列出模块信息:
# 列出所有依赖
go list -m all
# 列出特定模块的所有版本
go list -m -versions github.com/gin-gonic/gin
# 列出模块的详细信息
go list -m -json github.com/gin-gonic/gin
编辑 go.mod 文件:
# 添加依赖
go mod edit -require=github.com/gin-gonic/gin@v1.9.1
# 删除依赖
go mod edit -droprequire=github.com/gin-gonic/gin
# 添加 replace
go mod edit -replace=github.com/example/pkg=../pkg
# 删除 replace
go mod edit -dropreplace=github.com/example/pkg
# 设置 Go 版本
go mod edit -go=1.21
# 格式化 go.mod
go mod edit -fmt
# 更新所有依赖到最新版本
go get -u ./...
go mod tidy
# 只更新补丁版本
go get -u=patch ./...
go mod tidy
每次修改代码后运行:
go mod tidy
将 go.sum 文件提交到版本控制:
git add go.mod go.sum
git commit -m "update dependencies"
# 安装特定版本
go get example.com/pkg@v1.2.3
# 安装最新补丁版本
go get example.com/pkg@v1.2
# 安装最新次版本
go get example.com/pkg@v1
# 生成 vendor 目录
go mod vendor
# 使用 vendor 构建
go build -mod=vendor
# 检查代理配置
go env GOPROXY
# 设置国内代理
go env -w GOPROXY=https://goproxy.cn,direct
# 清理缓存
go clean -modcache
# 查看依赖图
go mod graph
# 更新特定依赖
go get example.com/pkg@latest
# 整理依赖
go mod tidy
# 设置私有模块
go env -w GOPRIVATE=github.com/myorg/*
# 配置 Git 使用 SSH
git config --global url."git@github.com:".insteadOf "https://github.com/"
# 清理缓存
go clean -modcache
# 重新下载
go mod download
| 工具 | 说明 | 推荐度 |
|---|---|---|
| Go Modules | 官方工具 | ⭐⭐⭐⭐⭐ |
| dep | 旧工具,已废弃 | ❌ |
| glide | 旧工具,已废弃 | ❌ |
| godep | 旧工具,已废弃 | ❌ |
# 1. 创建项目
mkdir myapp && cd myapp
# 2. 初始化模块
go mod init github.com/example/myapp
# 3. 创建 main.go
cat > main.go << 'EOF'
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
func main() {
fmt.Println("Gin version:", gin.Version)
fmt.Println("GORM version:", gorm.Version)
}
EOF
# 4. 下载依赖
go mod tidy
# 5. 运行项目
go run main.go
# 6. 查看依赖
go list -m all
# 7. 查看依赖图
go mod graph
# 项目结构
# workspace/
# ├── go.work
# ├── app/
# │ ├── go.mod
# │ └── main.go
# └── lib/
# ├── go.mod
# └── lib.go
# 创建工作区
go work init ./app ./lib
# go.work 内容
cat > go.work << 'EOF'
go 1.21
use (
./app
./lib
)
EOF
本章深入讲解了 Go 语言的依赖管理:
掌握依赖管理是构建可靠 Go 项目的基础。在下一章中,我们将学习如何创建和发布自己的模块。