Files
cs-note/hzh/GolangStar/Go语言基础/Go语言依赖管理.md
T

158 lines
4.7 KiB
Markdown
Raw Normal View History

2026-06-07 11:08:10 +08:00
---
2026-06-07 12:14:39 +08:00
tags: [go, golang, go基础语法, modules, go modules, 依赖管理]
create time: 2026-06-07 15:00
2026-06-07 11:08:10 +08:00
---
2026-06-07 12:14:39 +08:00
# Go 语言依赖管理
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
## 概述
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
Go Modules 是 Go 1.11+ 引入的官方依赖管理方案。本文讲解 go.mod/go.sum 的核心结构、常用命令和关键环境变量的配置。
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
## 正文
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
### 为什么 Go 需要 Modules?
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
在 Modules 出现之前,Go 依赖 `GOPATH` 管理——所有代码必须放在 `$GOPATH/src` 下。这导致:
- 项目路径与代码仓库路径不一致
- 依赖版本无法锁定
- 多项目间依赖冲突
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
Go Modules 让每个项目**自包含**其依赖信息,不再依赖 GOPATH。
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
### 核心环境变量
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
| 变量 | 用途 | 推荐值 |
|------|------|--------|
| `GO111MODULE` | 开关(auto/on/off) | `on`(Go 1.14+ 默认) |
| `GOPROXY` | 模块代理地址 | `https://goproxy.cn,direct`(国内) |
| `GOSUMDB` | 校验数据库 | `sum.golang.org`(默认) |
| `GOPRIVATE` | 私有仓库域名 | 按需设置 |
2026-06-07 11:08:10 +08:00
```bash
2026-06-07 12:14:39 +08:00
# 国内开发者推荐配置
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct
2026-06-07 11:08:10 +08:00
```
2026-06-07 12:14:39 +08:00
> [!info] ℹ️ `direct` 的含义
> `GOPROXY=https://goproxy.cn,direct` 表示先从 goproxy.cn 拉取,如果返回 404/410,则回源到原始仓库(如 GitHub)。
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
### GOPRIVATE:私有仓库
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
对于不在公共代理中的私有仓库:
2026-06-07 11:08:10 +08:00
```bash
2026-06-07 12:14:39 +08:00
go env -w GOPRIVATE="github.com/myorg/*,git.internal.company.com"
```
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
> [!tip] 💡 通配符支持
> `github.com/myorg/*` 会匹配 `myorg` 下的所有子仓库。
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
### go.mod 文件结构
2026-06-07 11:08:10 +08:00
```go
2026-06-07 12:14:39 +08:00
module example.com/myproject // 模块路径(import 的基础路径)
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
go 1.21 // 所需最低 Go 版本
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
require ( // 直接依赖
github.com/gin-gonic/gin v1.9.1
gorm.io/gorm v1.25.5
2026-06-07 11:08:10 +08:00
)
2026-06-07 12:14:39 +08:00
require ( // 间接依赖(自动传递)
github.com/gin-contrib/sse v0.1.0 // indirect
2026-06-07 11:08:10 +08:00
)
2026-06-07 12:14:39 +08:00
replace ( // 替换某个依赖
golang.org/x/image => github.com/golang/image v0.18.0
2026-06-07 11:08:10 +08:00
)
2026-06-07 12:14:39 +08:00
retract v0.2.0 // 撤回不推荐的版本
2026-06-07 11:08:10 +08:00
```
2026-06-07 12:14:39 +08:00
> [!note] 📝 关键字段说明
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
| 字段 | 作用 |
|------|------|
| `module` | 当前模块的唯一路径,import 语句以此为前缀 |
| `go` | 声明兼容的 Go 最低版本 |
| `require` | 依赖列表,分直接和间接两类 |
| `replace` | 将 A 替换为 B(可用于本地开发或镜像) |
| `exclude` | 排除某个特定版本(Go 1.16+) |
| `retract` | 声明某版本不应被使用(Go 1.16+) |
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
### indirect 标记
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
当你的项目依赖 A,A 又依赖 B,但 A 的 go.mod 缺少 B 时,你的项目中 B 会被标记为 `// indirect`。
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
执行 `go mod tidy` 后,无用的 indirect 依赖会被移除。
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
### +incompatible 标记
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
语义化版本要求:v2+ 的模块路径需包含 `/v2`。如果作者忘了改路径,版本号后面会加上 `+incompatible`:
2026-06-07 11:08:10 +08:00
```go
2026-06-07 12:14:39 +08:00
require github.com/pkg/errors v0.9.1+incompatible
2026-06-07 11:08:10 +08:00
```
2026-06-07 12:14:39 +08:00
功能上与普通版本无异,只是提醒开发者这个模块没有遵循语义化版本规范。
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
### go.sum:安全校验
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
`go.sum` 记录每个依赖的哈希值,确保下载的内容未被篡改:
2026-06-07 11:08:10 +08:00
```
2026-06-07 12:14:39 +08:00
github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA=
github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqk=
2026-06-07 11:08:10 +08:00
```
2026-06-07 12:14:39 +08:00
> [!warning] ⚠️ 不要手动编辑 go.sum
> 它由 Go 工具链自动生成和维护。
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
### 常用命令速查
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
| 命令 | 作用 |
|------|------|
| `go mod init module/path` | 初始化新模块 |
| `go get package@version` | 添加/更新依赖 |
| `go mod tidy` | 清理无用依赖,补充缺失依赖 |
| `go mod download` | 下载依赖到本地缓存 |
| `go mod graph` | 打印依赖图 |
| `go mod vendor` | 导出依赖到 vendor/ 目录 |
| `go mod verify` | 校验依赖完整性 |
| `go clean -modcache` | 清除模块缓存 |
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
> [!tip] 💡 日常开发工作流
> ```bash
> go get github.com/example/pkg@latest # 添加/升级依赖
> go mod tidy # 清理
> go build # 编译(自动检查一致性)
> ```
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
### 版本选择规则
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
| 情况 | 行为 |
|------|------|
| 有语义化标签(v1.2.3) | 取最大主版本标签 |
| 无标签 | 取 main 分支最新 commit,生成伪版本号 |
| 伪版本号 | `v0.0.0-yyyyMMddHHmmss-abcdef123456` |
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
### replace 的使用场景
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
当公共代理不可用时,用 replace 指向镜像或本地路径:
2026-06-07 11:08:10 +08:00
```go
2026-06-07 12:14:39 +08:00
replace golang.org/x/image => github.com/golang/image v0.18.0
```
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
或者指向本地开发路径:
2026-06-07 11:08:10 +08:00
2026-06-07 12:14:39 +08:00
```go
replace mycompany/internal/pkg => ../internal/pkg
2026-06-07 11:08:10 +08:00
```
2026-06-07 12:14:39 +08:00
> [!info] ℹ️ replace 不影响 import 语句
> 代码中仍然写 `import "golang.org/x/image"`,Go 会自动识别 replace 映射到实际路径。