>

简介

Go vendor 是 Go 1.5 官方引入管理包依赖的方式,需要把环境变量 GO15VENDOREXPERIMENT 设置为 1:

GO15VENDOREXPERIMENT=1

Go vendor 的项目管理方式在 Go 1.6 版本中得到正式引入,上述环境变量的值已经默认设置为 1 了(可以通过 go env 命令查看)。
另外,在此后的 Go 1.7 版本中,已经去除了该环境变量,从而默认开启 vendor 特性。

相比于传统的 go get 的方式来获取外部包(默认保存在 $GOPATH/src 中而不是项目自身目录中),使用 Go vendor 来管理外部依赖包(第三方库)的优势是显而易见的,因为它是通过将源码拷贝到当前工程的 vendor 目录下,这样,打包当前的工程代码到任意机器的 $GOPATH/src 下都可以通过编译,避免项目代码有外部依赖,迁移之后,还需要用 go get 去下载那些依赖包。

此外,传统的 go get 方式管理的包还有许多不可避免的缺陷,尤其是在当多个开发者之间在不同的机器上工作,有可能因为参与的时间不同,通过 go get 获取到的包的版本不同,甚至有可能某个 commit 之后发生了 API 的变更,导致在不同电脑上出现编译错误,从而造成原有的代码无法兼容的问题。下面列举一些依赖包可能出现的对原有项目造成影响的情况:

  • 引用的包已经被砍掉了?
  • 引用的包原作者或是维护团队忽然決定大改 API?
  • 引用的包忽然出現意外的错误(break code)? (当然有可能是底层 API 被 Google 改掉)
  • 想要维护整个包的稳定性,比如通过 go get 重新拉去的外部依赖包的版本又可能和工程开发时使用的不一致,导致潜在的编译错误问题。

虽然我们可以使用开源的工具 godep 去处理第三方依赖包的问题,但终归多了一个额外安装的过程,而 Go 在提供了默认的 vendor 模式之后就简化了这个过程。

使用方式

vendor 的使用非常简单,只需要在用户的工程项目目录中新建一个 vendor 目录,然后把依赖的第三方包放入这个目录中就可以了。vendor 模式开启的情况下,则对于工程源码中的 import 语句中引入的外部包,Go 会自动在 vendor 目录中搜索。
可以参考这个库 https://github.com/fatih/color 的源码结构来组织你的工程目录。

缺陷

虽然使用 vendor 的方式可以解决上述提出的问题,但是这种方式还有一些没有解决的问题,比如:

  • 无法精确的引用外部包进行版本控制,不能指定引用某个特定版本的外部包。由于 vendor 目录中的包只是简单的拷贝过来,一旦外部包升级,vendor下的代码不会跟着升级。
  • 而且 vendor 下面并没有元文件记录引用包的版本信息,这个引用外部包升级产生很大的问题,无法评估升级带来的风险;

### 开源解决方案 govendor

开源库 govendor 提供了一些方法来解决上述 go vendor 未解决的问题

govendor 工具可以平滑的将现有非 vendor 项目转换为 vendor 项目

简单用法:

  1. 执行 govendor init 就可以在当前项目目录生成 vendor 文件夹,vendor 文件家中有一个 vendor.json 文件记录了依赖包的信息。

  2. 执行 govendor add packagename 命令添加一个依赖包

  3. 如果需要更新或移除,可以参考一下工具的具体文档使用 update 或者 remove 命令

  4. 提供命令查看整个工程的依赖关系

    $ goverdor –list
    $ goverdor –list -v

  5. vendor.json 示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ cat vendor.json
{
"comment": "",
"ignore": "test",
"package": [
{
"path": "github.com/yeeuu/echoic",
"revision": "a7d6994f92e2dc60cff071ae38b204fbd4bd2a3f",
"revisionTime": "2015-12-18T11:14:29+08:00"
},
{
"path": "golang.org/x/net/context",
"revision": "1d9fd3b8333e891c0e7353e1adcfe8a612573033",
"revisionTime": "2015-11-13T15:40:13-08:00"
}
]
}

更多命令详见:
https://github.com/kardianos/govendor




参考:
http://thinkerou.com/2016-04/go-vendor/
http://www.infoq.com/cn/articles/golang-package-management