Golang的包依赖管理 (package dependency manager)

 Golang 的开发者对GOPATH都不陌生, 它是进行go 项目开发的’workspace’。 go项目的源码,可执行文件,以及依赖库的存放都是通过gopath的相关目录结构进行组织的,而且go原生的依赖管理也是使用GOPATH进行组织。 如当前项目中import “github.com/helloworld”, 则在使用go get编译当前项目时,”helloworkd”的源码会被download到$GOPATH/src/github.com/hellowrold的目录中。 而且go get的过程是递归的,helloworld中依赖的项目也会被逐一download到gopath当中。go get会调用对应的版本控制工具获取源码, 如果被下载的项目使用的git那么,go get 实际上就是调用的gitclone 复制一份源代码到本地,当然go get 也支持其他的一些版本控制工具。

 

我们知道GOPATH是可以指定多个目录的,例如下面这种情况。那么下面这种设置意味着什么呢?

 

GOPATH="/home/ansendong/golang:/var/www/personal/app1:/var/www/personal/app2:/var/www/personal/app3"

 

1)/home/ansendong/golang  是在GOPATH的第一个目录,所有的使用’go get’ 下载的依赖包全部会放到这里。

2)编译的时候go 会去GOPATH中包含的所有目录中,查找依赖的库, 当所有的目录都没有所依赖的库时,通过go get 去下载依赖包。

3)编译时,GO会在GOPATH中查找依赖,如果在GOPATH的目录中存在多个库的copy, 则编译器会使用第一个找到库的依赖。

 

这样第三方包就会默认放置在第一个路径中,而你可以在第二个路径下编写自己的代码。 虽然 Go 语言本身已经提供了相当强大的包管理方式了,但是仍然有一些问题:

1)隔离不同项目的环境,  第三方依赖没有版本控制,如果多个项目同事依赖同一个第三方库,但是存在版本冲突,就会出现麻烦。

2)控制某个依赖包的版本, go get总是下载最新版本的第三方包,而我们的目的只是想依赖某个稳定版本,如果第三方包的接口更新,就会导致构建失败。我们不能控制依赖的版本。

3) Go 本身的版本(相对简单)

 

结合实际的一些经验,依赖较多的大的项目建议使用 godep+ 独立的gopath的方式,即为单个项目建立唯一的gopath(建立单个workspace).

 

1,  使用独立的gopath彻底解决了隔离项目环境的问题

2,  使用godep可以记录当前依赖的版本,godep restore 会根据Godep.json中记录的依赖的版本,download所有的依赖到当前的GOPATH。

达到可重复构建的目的,同时也可以实现第三方依赖包

 

但是在一个项目中依赖另外一个使用dep管理依赖包的项目时还是有一些小问题的 , 真TMD绕嘴。

比如我的一个项目中使用到了kube-client,K8S当中的一个包, 而 K8S本身也是使用godep去管理它的依赖。

1)go get 我的项目A,  因为A import 了kube-client, 所有会download整个K8S到 GOPATH, 但是在这一步骤里并没有download K8S的依赖包到GOPATH, 为什么? 因为K8S的vendor目录中已经包含了kubernetes本身的依赖。

2)godep save ./… , 这个过程会把kubeclient的源码还有kubeclient的依赖包从GOPATH copy到项目A的vendor中。这一步报错,因为缺少kubernetesclient的依赖包,原因是上一步中没有把kubernetes的依赖包download到GOPATH。

3)回到K8S项目中, 调用godep restore. 把k8s的依赖包全部重新download到GOPATH中

4)回到项目A, 重新使用命令godep save ./…,  成功。 会把kubeclient 以及kubeclient的依赖copy到项目A的vendor目录当中。

 


你可能感兴趣的:(Golang)