Go 依赖管理经历了 3 个阶段,GOPATH、Go Vendor、Go Module。
- GOPATH
GOPATH
是 Go 语言的一个环境变量,它是 Go 项目的工作区。目录有 3 个结构:
- bin:项目编译的二进制文件
- pkg:项目编译生成的lib包
- src:项目源码
go get 会下载最新版本的包到 src 目录下。因为 src 下只能允许一个版本的存在,所以对于多个项目依赖同一个库的不同版本这种情况,GOPATH 管理模式就显得力不从心了。至此,Go Vendor 出现了。
- Go Vendor
1.5 版本推出了vendor
机制。就是每个项目的根目录下有一个 vendor 目录,里面存放了该项目的依赖包。go build
的时候会先去 vendor 目录中查找依赖,如果没有找到再去 GOPATH 目录下查找。这样每个项目引入一份依赖的副本,解决了多个项目需要使用同一个 package 依赖的冲突问题。
vendor 机制的缺点是,同一个依赖包如果不同工程想重用,都必须各自复制一份在自己的vendor目录下。不能重用,使得冗余度上升。
- Go Module
从 Go1.11 版本开始,官方推出Go module
作为包管理工具,在 Go 1.16 默认开启,可以看到在项目目录下有一个 go.mod 文件,且工程项目可以放在GOPATH路径之外。
go mod 使用
设置的命令如下:
go env -w GO111MODULE=on go env -w GOPROXY=https://goproxy.cn,direct 复制代码
可在命令行中输入:go env
查看 GO111MODULE=on 。
go mod 常用命令:
- go mod download: 下载模块到本地缓存,缓存路径是 $GOPATH/pkg/mod/cache
- go mod edit: 是提供了命令版编辑 go.mod 的功能,例如
go mod edit -fmt go.mod
会格式化 go.mod - go mod graph: 把模块之间的依赖图显示出来
- go mod init: 在当前文件夹下初始化一个新的 module,创建 go.mod 文件
- go mod tidy: 增加缺失的包,移除没用的包
- go mod vendor: 把依赖拷贝到 vendor 目录下
- go mod verify: 校验依赖
- go mod why: 解释为什么需要包和模块
- 创建 module
工程项目可以放在 GOPATH 路径之外,执行go mod init modulename
命令可以创建一个 go.mod 文件。在项目根目录建一个 go.mod 文件即可。
go.mod文件结构
- module :指定模块的名称 (路径)
- go :依赖的原生 Go SDK 版本
- require :项目所依赖的模块
- replace :可以替换依赖的模块
- exclude :可以忽略依赖的模块
- 添加依赖
在 Go1.16 版本之前,运行 go 命令(go run、go build、go test)时,会自动下载并修改 go.mod 文件。
在 Go1.16 版本中,运行go命令,如果 import 的依赖再 go.mod 文件中没有,就不会再自动下载,而会提示错误,需要手动执行 go get
命令下载对应的包。因为自动下载的方式,如果在导入的包没有提供任何依赖的情况下自动添加新的依赖,有可能会引起公共依赖包的升级等。
- go get更新依赖
- go get -u :更新到最新的次要版本或者修订版本(x.y.z)
- go get -u=patch :更新到最新的修订版本
- go get package@version :更新到指定的版本号version
- 运行 go get 如果有版本的更改,那么 go.mod 文件也会作出相应的更改。
- go.sum 文件
go.sum 是记录了所有依赖的 module 的校验信息,以防下载的依赖被恶意篡改,主要用于安全校验。格式如下:
<module> <version> <hash> <module> <version>/go.mod <hash> 复制代码
module 是依赖的路径。version 是依赖的版本号。如果 version 后面跟 /go.mod 表示对哈希值是 module 的 go.mod 文件;否则,哈希值是 module 的.zip文件。
go.mod 和 go.sum 文件都需要被加入版本管理中。