go语言依赖管理 | 青训营笔记

80 阅读3分钟

这是我参与「第五届青训营」伴学笔记创作活动的第 3 天

想要开发完整的项目依赖管理是不可或缺的,今天的内容是go语言依赖管理的实现方法,go语言的依赖管理主要围绕两个问题:①不同项目依赖的版本不同 ②控制依赖库的版本

依赖管理

go语言的依赖管理演进大体可以分为三个阶段:GOPATH、Go Vendor、Go Module

1、GOPATH

最早的时候,Go所依赖的所有的第三方库都放在GOPATH这个目录下面,GOPATH可以理解成配置的环境变量或者工作区,在GOPATH目录下有bin、pkg、src三个文件夹,通过go get命令下载最新版本的包到src目录下,而项目代码直接依赖于src中的代码
例如:
$ go get github.com/davyxu/cellnet

这样带来的弊端是,如果一台机器中同时有多个项目,每个项目依赖相同库的不同版本,这时就会导致冲突。

2、Go Vendor

为了给不同的项目一个单独的环境,go语言支持vendor机制,在每个项目文件夹下都有一个vendor文件夹,项目会先从vendor中寻找对应依赖,如果未找到则到GOPATH目录下寻找,可以类比于anaconda对于python虚拟环境的管理,当然两者差别还是很大的。通过vendor机制,不同的项目可以拥有不同的依赖库管理,通过vender模式实现的Go语言的第三方依赖管理工具有很多,如godep

但这样会导致一些问题,比如包版本更新时可能会对使用上一版本的项目造成影响,以及,虽然vendor使得每个项目对应的依赖不会重复混乱,但依赖库本身也可能依赖于其他库,如果出现两个库同时依赖于另一个库的情况,依然会导致冲突,这是由于vendor文件夹依然是把源码放进来,没有指定具体的版本信息导致的

3、Go Module

go语言最新的依赖管理方式采用Go Module机制,通过go.mod配置文件描述依赖,一个示例的go.mod文件如下
module github.com/Q1mi/studygo/blogger

go 1.12

require (
    github.com/DeanThompson/ginpprof v0.0.0-20190408063150-3be636683586
    github.com/gin-gonic/gin v1.4.0
    github.com/go-sql-driver/mysql v1.4.1
    github.com/jmoiron/sqlx v1.2.0
    github.com/satori/go.uuid v1.2.0
    google.golang.org/appengine v1.6.1 // indirect
)

关于版本的描述可以分为语义化版本和基于commit的伪版本两种方式,上述例子也已经体现

另一个部分则是通过中心仓库管理依赖的Proxy,在Proxy中缓存源站的依赖库内容,从而解决直接从源站拉取内容的不稳定性问题,同时proxy也可以分层,使用的工具命令依然是go get。

总结

依赖管理是开发项目时的必要步骤,同时也了解到早期go的依赖管理是饱受诟病的,之前学习过其他语言框架的依赖管理方法,其实与go语言依赖管理思想相近。