依赖管理差不多已经是现代编程语言的一个重要特性,目前常用的语言基本都有相应的依赖管理工具,比如PHP的Composer, js的npm等等,这些工具都能帮助我们更加方便的去使用第三方库,提升开发效率,还能避免一些因为依赖库版本问题导致的坑。

但是对于Golang,官方自带了一个包管理工具,只需要运行go get <package>就可以将需要的包的master分支拉到本地的GOPATH相应的目录下面,虽然说很方便,但是却有很大的缺陷:

  • 默认拉取master分支,不能拉取指定版本(当然,gopkg.in可以做到重定向,是一种解决方案)
  • 没有依赖包完整性校验,可能导致编译错误。特别是在国内,因为某些原因导致某些包拉取失败。

godep

vendor目录

在Golang 1.5版本,官方开始引入包管理的设计,加入vendor目录来支持本地包依赖管理(默认关闭,需要设置go环境变量GO15VENDOREXPERIMENT=1)。从1.6版本开始正式默认启用该特性。

这个特性方便之处是你可以把依赖包拷贝到项目的vendor目录下面,这样当go编译时,就会优先从项目vendor目录下面查找依赖包,如果找到,就不会再在GOPATH中查找。

存在的问题:

  • 版本问题没有解决
  • 复制依赖包,显得不那么方便

社区为了解决这些问题,基于vendor特性,出现了很多的管理工具,比如godep, govendor, glide,还有官方开发的dep

godep

地址: https://github.com/tools/godep

基本使用:

运行godep save命令,godep会扫描项目文件引入的第三方包,在项目目录下生成Godeps目录,并将依赖包、包版本号记录到Godeps/Godeps.json文件中;同时将项目中使用的第三方库复制到vendor目录下面(早期版本会复制到Godeps/_workspace目录下)。

新增依赖包:

1
2
3
4
5
go get <package>

// 在你的项目中引入(import)新增的包

godep save

更新依赖包:

1
2
3
go get -u <package>

godep update <package>

下载依赖包:

如果你下载的项目已经包含了Godeps.json文件,但是有些库在你本地可能不存在,这是你可以运行godeo restore命令,这样godep会按照Godeps/Godeps.json内列表,依次执行go get -d -v 来下载对应依赖包到GOPATH路径下。

govendor

地址: https://github.com/kardianos/govendor

快速开始

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 初始化项目
cd "my project in GOPATH"
govendor init

# 拉取指定版本的依赖包
govendor fetch golang.org/x/net/context@a4bbce9fcae005b22ae5443f6af064d80a6f5a55
govendor fetch golang.org/x/net/context@v1   # 获取标签名或分支名为v1.*.*的最新版本
govendor fetch golang.org/x/net/context@=v1  # 获取标签名或分支名为v1的版本.

# 根据之前的版本约束,将包更新到最新版本
govendor fetch golang.org/x/net/context

常用命令说明

  • govendor init: 初始化项目,自动创建vendor目录,会在vendor目录下生成一个vendor.json,记录依赖包列表以及版本号等信息。
  • govendor add +external: 如果你的项目已经开发了一段时间,而且之前是实用go get方式下载包,可以执行该命令,将会把项目中使用到的包复制到项目vendor目录下。
  • govendor fetch: 从远程仓库拉取或更新依赖包
  • govendor sync: 根据vendor.json文件从远程仓库拉取指定版本的依赖包(使用场景为有vendor.json文件,但是vendor不包含依赖库代码的情况)。

glide

地址: https://github.com/Masterminds/glide

glide的依赖包信息在glide.yaml和glide.lock中,前者记录了所有依赖的包,后者记录了依赖包的版本信息。

初始化

在项目下面执行glide init,会自动扫描已经存在的代码,并生成glide.yaml

编辑

针对刚刚产生的glide.yaml可以进行编辑,比如要指定版本号,可以添加version参数:

1
2
3
4
5
import:
- package: github.com/astaxie/beego
  version: ~1.7.2
- package: github.com/dgrijalva/jwt-go
  version: ~3.0.0

也可以直接使用glide config-wizard由程序引导你选择版本。

如果要让glide忽略部分package,可以这样修改

1
2
3
4
package: YOUR-PACKAGE
ignore:
- NEED-IGNORE-PACKAGE
import:

更新package

执行glide update会根据之前的设定,将需要的包安装到vendor目录下,并在glide.lock中记录。

新增package

使用glide get命令可以用来新增包,同时可以使用#来指定版本号。

1
2
3
glide get github.com/foo/bar

glide get github.com/foo/bar#^1.2.3

安装依赖

1
glide install

这个命令是在一个已经使用 glide 管理依赖的项目里,需要在新环境下重新安装依赖使用的,这个命令会按照 glide.lock 的信息,把所有的依赖拉取到本地,和 glide update 不同的是,glide update 会拉取最新的版本,并且会修改 glide.lock,而 glide install 只下载之前的依赖。

官方dep

地址: https://github.com/golang/dep

dep通过两个metadata文件来管理依赖:manifest文件Gopkg.toml和lock文件Gopkg.lockGopkg.toml可以灵活地描述用户的意图,包括依赖的 source、branch、version等。Gopkg.lock仅仅描述依赖的具体状态,例如各依赖的revision。Gopkg.toml可以通过命令生产,也可以被用户根据 需要手动修改,Gopkg.lock是自动生成的,不可以修改。

初始化

执行dep init即可,dep会分析应用程序所需要的所有依赖包,得出依赖包清单,并生成vendor目录,Gopkg.toml、Gopkg.lock文件。

新增依赖

1
2
3
4
5
# 引入该依赖包的最新版本
dep ensure -add github.com/pkg/foo

# 引入具有特定约束(指定版本)的依赖包
dep ensure -add github.com/pkg/foo@^1.0.1

更新配置

1
dep ensure -update

该命令会将Gopkg.lock中的约定依赖项更新为Gopkg.toml允许的最新版本。