包管理 #
Go 包管理概述 #
Go 1.4 及之前 #
- 必须设置
GOPATH
环境变量,且源代码必须存放在GOPATH
下 - 拉取外部依赖包时,总是拉取最新的版本,无法指定需要的版本
设置 GOPATH
环境变量有两个原因:
- 它规定了
go get
命令下载的依赖包的存储位置($GOPATH/src
) - 通过设置
GOPATH
,可以方便 Golang 计算出 import 的路径
Go 1.5 至 Go 1.10 #
每个项目的根目录下可以有一个 vendor 目录,里面存放了该项目的依赖的包
Go 1.11 至 Go 1.12 #
- 默认使用的还是 GOPATH 的管理方式
- 运行
export GO111MODULE=on
,使用Go Modules
GO111MODULE
为 off
时:
- 优先使用
vendor
目录下面的包, - 如果
vendor
下面没有搜索到,再搜索$GOPATH/src
下面的包, - 如果
$GOPATH
下面没有搜索到,那么搜索$GOROOT/src
下面的包
Go 1.13 及之后 #
Golang 的包管理默认使用 Go Modules
Go 包管理工具发展 #
monorepo #
所有的包都放在 GOPATH 里面,使用类似命名空间的包路径区分包
vendor #
从 Go 1.5
开始开始引入 vendor 包模式,如果项目目录下有 vendor 目录,那么 go 工具链会优先使用 vendor 内的包进行编译、测试等,
这之后第三方的包管理思路都是通过这种方式来实现,比如说由社区维护准官方包管理工具 dep
Dep #
Go 1.9
及之后
由于 Golang 作者跟 Dep 作者在 Dep 设计上的分歧,Golang 官方在 2018 年 5 月开始推 Go modules,并在 Go 1.13 中默认启用。 曾今自认为 Golang 官方的实验性工具就此没落,很少再有人维护了。 因此,建议 Dep 用户迁移到 Go modules。
Glide #
govendor #
Go Modules #
Go 1.11
-Go 1.12
,运行export GO111MODULE=on
,使用Go Modules
Go 1.13
之后,默认使用Go Modules
$GOPATH
不再作为 build 时导入的角色,
依赖包会存放在 $GOPATH/pkg/mod
目录下。
Go Modules 原理 #
命令 #
# 下载所有依赖
go mod download
# 升级次级或补丁版本号
go get -u rsc.io/quote
# 仅升级补丁版本号
go get -u=patch rscio/quote
# 整理并更新 go.mod
go mod tidy
# 仅仅修改 go.mod 配置文件的内容
go mod edit --droprequire=golang.org/x/crypto
# 查看 go.mod 内容
go list -m all
# json 格式输出
go list -m -json all
# 格式化 go.mod
go mod edit -fmt
go mod vendor #
Module-aware mode
vs GOPATH mode
#
Module-aware mode
is active by default whenever a go.mod
file is found in the current directory or in any parent directory.
GO111MODULE
- off
- the go command never uses module support. Instead it looks in vendor directories and GOPATH to find dependencies
- on
- the go command requires the use of modules, never consulting GOPATH.
- or auto (the default)
- Module support is enabled only when the current directory contains a
go.mod
file or is below a directory containing ago.mod
file.
- Module support is enabled only when the current directory contains a
- off
In module-aware mode, GOPATH no longer defines the meaning of imports during a build,
but it still stores downloaded dependencies (in GOPATH/pkg/mod
)
and installed commands (in GOPATH/bin
, unless GOBIN
is set).
replace #
go modules
下 import 不再支持使用相对路径导入包,例如 import "./mypkg"
,所以需要考虑 replace
本地替换的价值在于它提供了一种使自动生成的代码进入 go modules 系统的途径, 毕竟不管是 go tools 还是 rpc 工具,这些自动生成代码也是项目的一部分,如果不能纳入包管理器的管理范围想必会带来很大的麻烦。
replace 不会生成 go.sum
信息
#
使用本地包进行替换时并不会生成 go.sum
所需的信息,所以 go.sum
文件也没有生成。
replace 命令只能管理顶层依赖
#
一个包是顶层依赖还是间接依赖,取决于它在本 module 中是否被直接 import,而不是在 go.mod 文件中是否包含 // indirect
注释。
不管是直接编辑还是 go mod edit 修改,我们为 go.mod 添加的信息都只是对 go mod 的一种提示而已, 当运行 go build 或是 go mod tidy 时 golang 会自动更新 go.mod 导致某些修改无效,
go.sum #
go.sum 是一个构建状态跟踪文件。它会记录当前 module 所有的顶层和间接依赖,以及这些依赖的校验和,从而提供一个可以 100% 复现的构建过程并对构建对象提供安全性的保证。
应该把 go.sum 和 go.mod 一同添加进版本控制工具的跟踪列表,同时需要随着你的模块一起发布。如果你发布的模块中不包含此文件,使用者在构建时会报错,同时还可能出现安全风险(go.sum 提供了安全性的校验)。
go.sum 不是锁文件 #
npm 的 package-lock.json 是锁文件,go.sum 不是。
go.sum 同时还会保留过去使用的包的版本信息,以便日后可能的版本回退,这一点也与普通的锁文件不同。所以 go.sum 并不是包管理器的锁文件。
go mod vendor
#
这个命令并不能让你从 godep 之类的工具迁移到 go modules,它只是单纯地把 go.sum 中的所有依赖下载到 vendor 目录里
使用 go build -mod=vendor
来构建项目
参考:
叶王 © 2013-2024 版权所有。如果本文档对你有所帮助,可以请作者喝饮料。