在Go中,如果您引用另一个包,例如在GitHub上的东西,然后Go总是从master
分支获得最新版本。虽然这对于开发很有用,但我认为这是生产中的一个问题:这样一种构建是不可重现的。
那么,Go中修复依赖项版本的正确方法是什么,以及如何有效地处理这种情况?
一位朋友给我指了godep,这看起来很好,但我想知道有什么替代方案,以及godep有什么好/坏?
使用Go 1.11更新2018
Dependencies should now be referenced with modules(来自the vgo project):
Go 1.11增加了对称为“模块”的新概念的初步支持,这是
GOPATH
的替代方案,集成了版本控制和软件包分发支持。 使用模块,开发人员不再局限于在GOPATH
内部工作,版本依赖性信息是显式但轻量级的,并且构建更可靠和可重复。
见Defining a module。 (和original design proposal)
2015年6月更新:第一次支持vendoring正在进入Go 1.5! 见c/10923/:
当
GO15VENDOREXPERIMENT=1
在环境中时,此CL根据Go 1.5供应商提议更改导入路径的分辨率:
- 如果有一个源目录
d/vendor
,那么,当编译一个源自d
的子树中的源文件时,import "p"
被解释为import "d/vendor/p"
(如果存在)。- 当存在多种可能的分辨率时,最具体(最长)的路径获胜。
- 必须始终使用简短形式:没有导入路径可以明确包含“
/vendor/
”。- 在vendored包中忽略导入注释。
2015年3月更新:go团队正在考虑定义与语言相结合的go依赖管理系统:辩论是in this thread。
我们认为现在是时候开始解决依赖性和销售问题了,特别是在出现太多冲突工具并在Go生态系统中破坏最佳实践之前,不必要地使工具复杂化。如果社区能够以标准的方式融入供应商,那将是一件好事。
我们的建议是Go项目,
- 官方建议使用导入重写(而不是internal修改)作为引入依赖关系的规范方法来销售到“
GOPATH
”目录。- 为依赖项和vendoring定义了一个通用的配置文件格式
- 在Go 1.5中没有对
cmd/go
进行代码更改。诸如“godep
”或“nut
”之类的外部工具将实现1)和2)。我们可以在Go 1.6+中重新评估包括这样的工具。
godep的一个可能的缺点是你不能再直接使用“go build”或“go test”。
您需要在这些命令之前加上godep
(或键入godep save
)。
另一种选择是glide,它与经典的go命令保持兼容。
- 管理项目特定的GOPATH
- 轻松依赖管理
- 支持版本控制包
- 支持别名包(例如,用于处理github分支)
- 无需“vendoring”或修改import语句
- 使用所有go工具
更一般地,文章“Know your guarantees, Go edition”很有趣:
这也是一个深思熟虑的选择,当Go作者认为权衡不利时,他们选择不实施某项功能。
他们做出这种选择的一个低级别原因是避免编译速度慢和臃肿的二进制文件(这是同一枚硬币的两面)。 请记住,包依赖于其他包。所以
Foo
可能依赖于Bar
2.1。Foo
也可能依赖于Baz
,而Bar
依赖于http://labix.org/gopkg.in 1.9,而且依赖于树。这意味着要编译和链接几个相同代码的副本。根据同一个软件包的多个版本,还意味着知道哪个版本正在调用,从而依赖性混乱渗透到您的源代码中。
这导致我们对Go平台支持这一特性的高层次推理:他们没有一个他们认为可以接受的逻辑解决方案。并不是他们不理解这个问题;就是这样,目前还没有他们喜欢的解决方案。因此,他们选择的功能不会超过回归功能。
您处理依赖关系,就像您在其他语言中处理依赖关系一样:您的供应商。对于Go,没有Nexus可以进行销售,因此大多数只是将外部库复制到“供应商”文件夹中,这里有一些工具可以帮助您。就个人而言,我发现所有这些“修复版本”的恐慌有点夸张,因为它没有很好的工作。
你可能想看看qazxswpoi并搜索golang-nuts进行依赖管理。我认为甚至有一个专门用于此的邮件列表。