依赖管理
java里有一个叫maven的包管理工具,go也有一个叫go mod的管理工具,可以管理项目引用的第三方包版本、自动识别项目中用到的包、自动下载和管理包。
演进
GOPATH->GO Vendor -> GO Module
GOPATH
- bin:项目编译的二进制文件
- pkg:中间产物
- src:项目源码,直接依赖
- 弊端:A和B依赖于某一个package的不同版本,无法实现package的多版本控制
Go Vendor
vendor是项目缓存,为了防止开源代码项目被删除无法引用下载,会使用vendor来做缓存管理,它是独立的,可以手动管理引用的包,代码包查找的顺序是向上冒泡
通过每个项目引入一份依赖的副本,解决GoPATH的问题
- 弊端:无法控制依赖的版本,更新项目有可能出现依赖冲突,导致编译错误
Go Module
- 使用go mod仓库中可以不用再上传依赖代码包,防止代码仓库过大浪费以及多个项目同时用包时的浪费
- 可以管理引用包的版本,这一点是gopath(src模式)和vendor做不到的
- 如果依赖gopath不同项目如果引用了同一个软件包的不同版本,就会造成编译麻烦
- gopath是go之前的默认策略,每个项目在运行时都要严格放在
src目录下,而go mod不用
通过go.mod文件管理依赖包版本
主版本2+模块会在模块路径增加/vN后缀
对于没有go.mod文件并且主版本2+的依赖,会+incompatible
incompatible表示不兼容标识,假如其当前版本为v3.6.0,因为其Module名字未遵循Golang所推荐的风格,即Module名中附带版本信息,我们称这个Module为不规范的Module。 在使用上没有区别,如果是我们自己开发的module,需要从xxx.com/xxx变到xxx.com/xxx/v2indirect是指间接依赖的包,比如 a module 使用了 b module,但b module的go.mod不完整,或者未启用 go module的话,会把未记录在b的go.mod中又依赖了的包作为间接依赖,放到a的go.mod文件里
原来的包管理方式
- 在不使用额外的工具的情况下,
Go的依赖包需要手工下载, - 第三方包没有版本的概念,如果第三方包的作者做了不兼容升级,会让开发者很难受
- 协作开发时,需要统一各个开发成员本地
$GOPATH/src下的依赖包 - 引用的包引用了已经转移的包,而作者没改的话,需要自己修改引用。
- 第三方包和自己的包的源码都在
src下,很混乱。对于混合技术栈的项目来说,目录的存放会有一些问题
新的包管理模式解决了以上问题
- 自动下载依赖包
- 项目不必放在
$GOPATH/src内了 - 项目内会生成一个
go.mod文件,列出包依赖 - 所以来的第三方包会准确的指定版本号
- 对于已经转移的包,可以用
replace申明替换,不需要改代码
依赖分发-回源
Github、SVN
无法保证构建的稳定性、无法保证依赖的可用性,会增加代码托管平台的压力
Go Proxy:缓存一些版本,更可靠、稳定
go get
go mod
go mod init:初始化go mod, 生成go.mod文件,后可接参数指定 module 名,上面已经演示过。
go mod download:手动触发下载依赖包到本地cache(默认为$GOPATH/pkg/mod目录)
go mod graph:打印项目的模块依赖结构
go mod tidy :添加缺少的包,且删除无用的包
go mod verify :校验模块是否被篡改过
go mod why:查看为什么需要依赖
go mod vendor :导出项目所有依赖到vendor下
写入go.mod有两种方法:
- 只要在项目中有 import 并使用或者使用下划线强制占用,然后 go build 时 go module 就会自动下载并添加。
go mod tidy
三要素:
配置文件,描述依赖 go.mod
中心仓库管理依赖库 Proxy
本地工具 go get/mod