Go Modules 基础

30.1 什么是 Go Modules

Go Modules 是 Go 1.11 引入的官方依赖管理系统,用于解决 Go 语言的依赖管理问题。在 Modules 出现之前,Go 使用 GOPATH 和 vendor 目录来管理依赖,这些方式都有各种问题。

Modules 的优势

  1. 版本控制:明确指定依赖的版本
  2. 语义化版本:支持语义化版本控制
  3. 可重现构建:确保不同环境构建结果一致
  4. 模块化:每个目录可以是一个独立的模块
  5. 私有模块支持:支持私有仓库

go.mod 文件

go.mod 是模块定义文件,位于项目根目录:

module github.com/example/myproject

go 1.21

require (
    github.com/gin-gonic/gin v1.9.1
    gorm.io/gorm v1.25.5
)

30.2 初始化模块

使用 go mod init

# 初始化新模块
go mod init github.com/example/myproject

# 查看生成的 go.mod
cat go.mod

生成的 go.mod 文件:

module github.com/example/myproject

go 1.21

项目结构示例

myproject/
├── go.mod
├── go.sum
├── main.go
└── pkg/
    └── utils.go

30.3 添加依赖

自动添加依赖

package main

import (
    "fmt"
    "github.com/gin-gonic/gin"
)

func main() {
    r := gin.Default()
    r.GET("/", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "Hello, World!",
        })
    })
    r.Run(":8080")
}

运行 go buildgo run main.go,Go 会自动下载依赖并更新 go.mod

go run main.go

手动添加依赖

# 添加特定版本
go get github.com/gin-gonic/gin@v1.9.1

# 添加最新版本
go get github.com/gin-gonic/gin

# 添加指定分支
go get github.com/gin-gonic/gin@main

go.mod 更新后的内容

module github.com/example/myproject

go 1.21

require (
    github.com/gin-gonic/gin v1.9.1
)

30.4 go.sum 文件

go.sum 文件记录了所有依赖的校验和,确保依赖的完整性和安全性。

go.sum 的作用

  • 记录每个依赖包的哈希值
  • 防止依赖被篡改
  • 确保团队使用相同的依赖版本

go.sum 示例

github.com/gin-gonic/gin v1.9.1 h1:...
github.com/gin-gonic/gin v1.9.1/go.mod h1:...
github.com/golang/protobuf v1.5.3 h1:...
github.com/golang/protobuf v1.5.3/go.mod h1:...
...

注意:不要手动编辑 go.sum 文件,它由 Go 工具自动管理。

30.5 依赖版本管理

语义化版本

Go Modules 遵循语义化版本规范:

  • v1.2.3:主版本.次版本.修订版本
  • v1.2.3-alpha.1:预发布版本
  • v1.2.3+20130313144700:构建元数据

版本查询

# 查看可用版本
go list -m -versions github.com/gin-gonic/gin

# 查看当前版本
go list -m github.com/gin-gonic/gin

# 查看所有模块
go list -m all

升级依赖

# 升级到最新版本
go get -u github.com/gin-gonic/gin

# 升级所有依赖
go get -u ./...

# 升级到特定版本
go get github.com/gin-gonic/gin@v1.10.0

# 升级补丁版本
go get -u=patch github.com/gin-gonic/gin

降级依赖

# 降级到特定版本
go get github.com/gin-gonic/gin@v1.8.0

30.6 整理依赖

go mod tidy

go mod tidy 会:

  • 添加代码中使用但未在 go.mod 中声明的依赖
  • 删除 go.mod 中声明但代码中未使用的依赖
  • 更新 go.sum 文件
go mod tidy

go mod verify

验证依赖的完整性:

go mod verify

go mod why

查看为什么需要某个依赖:

go mod why github.com/gin-gonic/gin

30.7 下载依赖

go mod download

下载所有依赖到本地缓存:

# 下载所有依赖
go mod download

# 下载特定模块
go mod download github.com/gin-gonic/gin

# 查看下载的依赖
go mod download -json github.com/gin-gonic/gin

依赖缓存位置

Go Modules 会将依赖下载到本地缓存:

  • Windows%USERPROFILE%\go\pkg\mod
  • macOS/Linux~/go/pkg/mod

30.8 替换依赖

本地模块替换

在开发时,可以使用本地模块替换远程依赖:

module github.com/example/myproject

go 1.21

require (
    github.com/example/utils v1.0.0
)

replace github.com/example/utils => ../utils

私有模块替换

module github.com/example/myproject

go 1.21

require (
    github.com/example/private v1.0.0
)

replace github.com/example/private => gitlab.com/example/private v1.0.0

使用 go mod edit

# 添加 replace 指令
go mod edit -replace=github.com/example/utils=../utils

# 删除 replace 指令
go mod edit -dropreplace=github.com/example/utils

30.9 供应商模式

go mod vendor

将依赖复制到 vendor 目录:

go mod vendor

使用 vendor 构建

# 使用 vendor 目录构建
go build -mod=vendor

注意:Go 1.16+ 默认使用模块缓存,vendor 模式主要用于特殊场景。

30.10 私有模块

配置 GOPRIVATE

告诉 Go 工具哪些是私有模块:

# 设置私有模块前缀
go env -w GOPRIVATE=github.com/example/*,gitlab.com/example/*

# 设置私有代理
go env -w GOPROXY=https://goproxy.cn,direct

使用私有模块

module github.com/example/myproject

go 1.21

require (
    github.com/example/private v1.0.0
)

30.11 常用命令总结

命令说明
go mod init初始化新模块
go mod tidy整理依赖
go mod download下载依赖
go mod verify验证依赖
`go mod vendor``生成 vendor 目录
go get添加或更新依赖
go list -m列出模块
go mod why查看依赖原因
go mod edit编辑 go.mod

30.12 实战示例

创建一个完整的项目

# 1. 创建项目目录
mkdir myproject
cd myproject

# 2. 初始化模块
go mod init github.com/example/myproject

# 3. 创建 main.go
cat > main.go << 'EOF'
package main

import (
    "fmt"
    "github.com/gin-gonic/gin"
)

func main() {
    r := gin.Default()
    r.GET("/", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "Hello, World!",
        })
    })
    r.Run(":8080")
}
EOF

# 4. 运行项目(自动下载依赖)
go run main.go

# 5. 整理依赖
go mod tidy

# 6. 查看依赖树
go mod graph

多模块项目

workspace/
├── go.work
├── app/
│   ├── go.mod
│   └── main.go
└── utils/
    ├── go.mod
    └── utils.go

创建工作区:

# 创建 go.work
go work init ./app ./utils

# 查看工作区
go work use

30.13 小结

本章介绍了 Go Modules 的基础知识:

  1. 模块初始化:使用 go mod init 初始化项目
  2. 依赖管理:使用 go get 添加和更新依赖
  3. 版本控制:支持语义化版本控制
  4. go.sum:确保依赖的完整性和安全性
  5. 依赖整理:使用 go mod tidy 整理依赖
  6. 私有模块:配置 GOPRIVATE 支持私有仓库

Go Modules 是现代 Go 项目的标准依赖管理方式,掌握它能让你更好地管理项目依赖。在下一章中,我们将学习更多关于依赖管理的知识。