变迁
GOPATH -> Go Vendor -> Go Mod
GOPATH
$GOPATH: 项目根路径
- src :项⽬源代码
- bin :项目编译的二进制文件
- pkg :项目编译的中间产物,加速编译
运行方式
- 所有工程代码要求放在GOPATH/src目录下
- go get 下载最新版本的包到src目录下,如
go get https://github.com/golang/oauth2,下载后对应目录$GOPATH/src/github.com/golang/oauth2
缺点
- 没有版本控制的概念
- 所有项目都要放在 GOPATH/src目录下,不在GOPATH/src目录下,不在 GOPATH/src目录下,不在GOPATH/src 下就不能编译
Go Vendor
在每个项目下都创建一个 vendor目录,每个项目所需的依赖都只会下载到自己vendor目录下,在使用包时,会先从当前项目下的 vendor 目录查找,然后GOPATH 中查找,都没找到最后在GOROOT中查找
优点
通过每个项目引入一份依赖的副本,解决了多个项目需要同一个package依赖的冲突问题
缺点
- 没有版本控制的概念
- 更新项目有可能出现以来冲突,导致编译出错
Go Mod
- 通过go.mod文件管理依赖包版本
- 通过go get/go mod 指令工具管理依赖包
优点
- 可以管理依赖的版本
- 工程不用全放在gopath/src
三要素
- 配置文件,描述依赖 go.mod
- 中心仓库管理依赖库 Proxy
- 本地工具 go get/mod
依赖配置
go.mod
bash
复制代码
# module:用于定义当前项目的模块路径,依赖管理基本单元
module github.com/eddycjy/module-repo
# go:用于标识当前模块的 Go 语言版本,值为初始化模块时的版本
go 1.16
# require:用于设置一个特定的模块版本,单元依赖
require (
example.com/apple v0.1.2
example.com/banana v1.2.3
example.com/banana/v2 v2.3.4
example.com/pear // indirect # indirect 标识表示该模块为间接依赖
example.com/strawberry // incompatible
)
#incompatible
主版本2+模块会在模块路径增加/vN后缀
对于没有go.mod文件并且主版本2+的依赖,会+incompatible
# exclude:排除一个特定的模块版本。
exclude example.com/banana v1.2.4
# replace:用于将一个模块版本替换为另外一个模块版本。
replace example.com/banana => example.com/fish
version
- 语义化版本:
v{major}.{minor}.{patch}如V1.3.0 - 基于commit伪版本: 一般用在预发布版本上,直接利用代码仓库的版本信息转化为模块版本,比如
v0.0.0-20230109021931-daa7c04131f5
依赖分发
回源
依赖分发用于表示可以使用何种方式获取依赖,依赖可以从各种代码仓库中取得
问题
- 无法保证构建稳定性:如软件作者可以直接在代码平台增加/修改/删除软件版本
- 无法保证依赖可用性:如软件作者可以直接在代码平台删除软件
- 增加第三方压力:如代码托管平台负载问题
Proxy
Go Proxy是一个服务站点,他会缓存源站中的软件内容,使得软件版本不会改变,并且在源站软件删除之后仍然可用,如果使用了Go Proxy之后,构建时会直接从Go Proxy站点拉取依赖,从而解决了上述问题
Go Proxy
Go Proxy通过设置GO PROXY环境变量来表示,比如:GOPROXY="https://proxy1.cn, https://proxy2.cn, direct
命令
go get: 获取依赖
使用方法:
go get example.org/pkg
- @update 默认
- @none 删除依赖
- @v1.1.2 tag版本
- @23dfdd5 特定的commit
- @master 分支的最新commit
go mod
- init 初始化,创建go.mod文件
- download 下载模块到本地缓存
- tidy 增加需要的依赖,删除不需要的依赖