Golang 是通过 vendor 来管理依赖的,它将所有的依赖,根据引用路径按照一定目录结构放在 vendor 目录下。这样会导致一个问题:如何同时引用一个依赖的多个版本? 很明显,Golang 的这种依赖管理模式,是解决不了这个问题。下面介绍一种解决该问题的比较有意思的方法。
问题描述
场景 1
v1.0v2.0
A ------> B
|
|
|
|
|
v2.0 |v1.0
|
|
C
场景 2
假设程序 A 需要同时支持 Gitlab v3 和 v4 的 API,但是其依赖的第三方库缺不能同时支持这两种 API。因此,程序 A 需要引入第三方依赖的两个版本,才能满足需求。
A
/
/
/
/
/
gitlab v3 gitlab v4
在上述两种场景下,使用 dep 包管理工具的话,就会出现版本冲突的问题。
解决方法
Fork 依赖
v1.0v2.0v2.0v2.0
引用 fork 出来的 B,那是不是所有路径都得发生变化呢?可以通过 dep 提供的参数 source,将原来的引用路径指向自己 fork 的地址。dep 的更多用法,可以参考之前的博客《Golang 依赖管理工具:Dep》。
例如:
[[constraint]]
name = "github.com/test/B"
# source 指定依赖的来源。
source = "github.com/my/B"
[[constraint]]
name = "github.com/test/C"
version = "2.0.0"
gopkg.in
采用 fork 的方式,虽然能够解决问题,但是更像是一种 workaround。这种方式会产生两份代码,很容易导致代码不一致,增加维护成本。
gopkg.in 支持 URL 中带 version,然后重定向到 Github 中相应的 version。 gopkg.in 的优势是 URL 简洁,轻量级,自身并不托管代码,而是重定向到 Github。
gopkg.in/xanzy/go-gitlab.v0
Version number
v0v0