Skip to content

在 GOPATH 时代,所有代码必须放在一个特定的工作目录下($GOPATH/src),不同项目依赖的包只能下载到同一个地方,无法隔离版本。Modules 就是为了解决这个问题

Go Modules 是 Go 语言的官方依赖管理工具,自 Go 1.11 版本开始引入,在 Go 1.16 版本成为默认的依赖管理模式

概念

模块(Module):包含 go.mod 文件的目录树,该文件定义了模块的路径、Go 版本要求和依赖关系

版本(Version):遵循语义化版本控制(Semantic Versioning)的标识符,格式为 vMAJOR.MINOR.PATCH

依赖图(Dependency Graph):模块及其所有传递依赖的层次结构,Go 工具会自动解析和维护

一个 Module 就是一个版本化的包集合,它是一个目录树,根目录下有一个 go.mod 文件。这个文件描述了这个模块的名字、Go 版本、以及它依赖的外部模块

go.sum 文件用于记录每个依赖的源代码哈希,确保下次下载的还是同一份代码,没被篡改

go.mod 文件

go
module example.com/project // 项目名

go 1.21 // 使用go版本

// 依赖内容
require (
    github.com/gin-gonic/gin v1.9.1
    golang.org/x/sync v0.3.0
)

// 用本地路径替换线上版本(常用于调试本地包)
replace example.com/old => ../local/old

// 排除某个有问题的版本
exclude golang.org/x/text v0.3.7

// 声明收回已发布的版本(表示该版本不应被使用)
retract v1.0.0 // 因为有严重bug

版本选择机制

Go Modules 使用最小版本选择(MVS)算法

77c43d67-72d4-45c5-a53b-c4cab6325762.png (1372×602)

使用

初始化模块

命令格式:go mod init [模块路径]

初始化一个新模块,在当前目录创建 go.mod 文件。这个模块路径将来会作为其他项目引用当前项目代码时的唯一标识符(导入路径前缀)

检查模块

命令格式:go mod tidy

扫描代码中所有的 import,把缺的依赖加到 go.mod,把没用的删掉,并更新 go.sum

操作包

命令格式:go get [包]@[版本]

修改依赖的版本。可以升级、降级,或者下载一个新包

go
go get github.com/gin-gonic/gin@v1.8.2    # 指定版本
go get -u github.com/gin-gonic/gin        # 升级到最新小版本

下载包(缓存)

命令格式:go mod download

只把 go.mod 里列出的模块下载到本地缓存($GOPATH/pkg/mod

移动到依赖库(项目)

命令格式:go mod vendor

把依赖的源代码从缓存拷一份到项目里的 vendor 文件夹

vendor 文件夹可以理解为:项目的“专属本地依赖仓库”

构建时可以 go build -mod=vendor,只依赖 vendor 里的代码,不连网

打印关系图

命令格式:go mod graph

打印整个模块的依赖关系图

包引用路径

命令格式:go mod why [包]

解释“为什么项目需要这个包?”,会显示从主模块到这个包的最短引用路径(列出调用链)

编辑mod

命令格式:go mod edit

用命令行编辑 go.mod,比如替换路径、添加 require。不会触发网络

清除mod

命令格式:go clean -modcache

清空本地模块缓存(就是删掉 $GOPATH/pkg/mod 里所有下载的包)。使用这个命令之后下一个 go build 会重新下载一切

查看全部依赖版本

命令格式:go list -m all

列出当前模块和它所有依赖(直接+间接)的精确版本