我正在接触 Go,虽然我理解并欣赏 Go 所基于的简单 原则,但我想了解放弃 背后的基本原理在它们的依赖项获取工具 go get
和 import
语句中内置包版本控制方法。
如果我理解正确,go get
和 import
从 HEAD
获取包,它们无法引用分支或标签.虽然有像 gopkg.in 这样的工具规避此限制的官方工具链:
- 强制开发人员为其产品的主要(中断)版本创建单独的存储库。
- 它不允许消费者在次要版本或微型版本之间降级,以防万一在较新的版本中发现错误。
说实话,事情并不那么容易,因为包版本控制需要一种策略来处理冲突的传递依赖关系,例如X
依赖于 A
和 B
,它们分别依赖于不同版本的 C
。
来自 Java 背景,似乎这种限制确实带来了一些风险和问题,其中包括:
产品/包的演变和第 3 方部门公共(public) API 的破坏是不可避免的,因此版本控制必须是工具链恕我直言中的一等公民。
Git-repo-per-version 策略非常低效:
- 包的整体 Git 历史丢失或分散在存储库中(版本之间的合并、向后移植等)
- 与传递依赖性的冲突仍然可能发生,并且不会被发现,因为语言或工具链首先强加任何语义以允许检测。
企业采用可能会受到阻碍,开发团队可能会回避这种语言,因为:
- 总是拖入
HEAD
意味着他们无法控制或卡住他们的第 3 方部门,从而导致潜在的不可预测的最终产品。 - 可能缺乏人力来不断更新他们的产品并使用上游的
HEAD
进行测试(并非世界上每家公司都是 Google :))。
- 总是拖入
虽然我确实理解后一种风险可以而且必须通过持续集成来减轻,但它并没有解决问题的根本根源。
我缺少什么信息?在人手有限的企业部署Go时如何处理包上游变更?
最佳答案
正在由 vendoring 处理这是 Go 1.5 的一部分,作为一项实验性功能,如果在其环境中使用 GO15VENDOREXPERIMENT=1
运行 go 命令,则可以启用它,并将成为 Go 1.6 中的“完整”功能。另见 Vendor Directories .
可以找到导致 Go 1.5 Vedor 实验的原始讨论 here .
vendoring 的本质是创建一个名为vendor
的文件夹,并放置您的代码所依赖的包的确切版本。 vendor
文件夹中的代码只能由根于 vendor
的父目录树中的代码导入,您可以从 vendor
导入包使用导入路径,就好像 vendor
将是 workspace/src
文件夹(也就是说,导入路径省略了直到并包括 vendor 元素的前缀)。
例子:
/home/user/goworkspace/
src/
mymath/
mymath.go
vendor/
github.com/somebob/math
math.go
在此示例中,github.com/somebob/math
是 mymath
包(来自 mymath.go
)使用的外部包。它可以从 mymath.go
中使用,如果它是这样导入的:
import "github.com/somebob/math"
(而不是 import mymath/vendor/github.com/somebob/math
这会很糟糕。)
关于go - Go 1.5 中的包版本管理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34775722/