Golang依赖管理最佳实践

Ric*_*nop 39 go

在Golang中,我们可以在GitHub上指定开源库作为依赖项.例如:

import "github.com/RichardKnop/somelibrary"
Run Code Online (Sandbox Code Playgroud)

这将尝试根据您的Go版本查找分支,如果我理解正确,则默认为master.

因此无法导入依赖项的特定版本,例如:

import "github.com/RichardKnop/somelibrary#v1.4.8"
Run Code Online (Sandbox Code Playgroud)

在Go中管理依赖关系的最佳实践是什么?

我可以看到两种方法.

I.版本模块

是否为具有重大变化的主要版本创建新模块?

例如,我的Go库可以定义模块v1和v2,那么你可以这样做:

import "github.com/RichardKnop/somelibrary/v1"
Run Code Online (Sandbox Code Playgroud)

要么:

import "github.com/RichardKnop/somelibrary/v2"
Run Code Online (Sandbox Code Playgroud)

根据您的需要.对v1或v2所做的任何更改都不需要破坏任何API或工作功能.

II.分叉

这将使您完全控制Go代码所需的外部依赖项版本.

例如,您可以将github.com/RichardKnop/somelibrary分叉到您自己的GitHub帐户中,然后在您的代码中执行以下操作:

import "github.com/ForkingUser/somelibrary"
Run Code Online (Sandbox Code Playgroud)

然后你必须分叉所有外部依赖,这似乎有点矫枉过正.但是,它可以让您完全控制版本.您可以将叉子保留在您知道正在使用代码的版本中,并且只有在检查新版本的依赖项不会破坏任何内容后才能更新分叉.

思考?

Ain*_*r-G 15

2018年2月:如果将vgo集成到工具链中,下面提出的销售方法(2015/2016)可能会消失.
请参阅下面的答案.


2015年8月版: Go 1.5附带内置(但仍为实验性)的支持.设置环境变量GO15VENDOREXPERIMENT将使go build和朋友在./vendor目录中查找包以及GOPATH.有关详细信息,请参阅VonC的答案设计文档.


III.Vendoring

AFAIK,这是确保您的构建具有可再现性和可预测性的最广泛使用的方法.Go团队本身在他们的回购中使用vendoring.Go团队现在讨论统一依赖清单文件格式.来自Go工具链开发者邮件列表:

在Google的内部源代码树中,我们将所有依赖项供应(复制)到源代码树中,并且最多只有一个任何给定外部库的副本.我们只相当于一个GOPATH并重写我们的导入以引用我们的销售副本.例如,想要使用"golang.org/x/crypto/openpgp"的Google内部的Go代码会将其导入为"google/third_party/golang.org/x/crypto/openpgp"之类的内容.

(......)

我们的建议是Go项目,

  • 官方建议将导入重写(不是GOPATH修改)作为引入依赖关系的规范方法进入"内部"目录.

  • 为依赖项和vendoring定义了一个通用的配置文件格式

  • 在Go 1.5中没有对cmd/go进行代码更改.诸如" godep "或" nut "之类的外部工具将实现1)和2).我们可以在Go 1.6+中重新评估包括这样的工具.


Von*_*onC 11

注意:2015年6月,第一次支持售卖出现在Go 1.5中!

c/10923 /:

GO15VENDOREXPERIMENT=1在环境中,这种CL变化的根据围棋1.5供应商建议的进口路径的分辨率:

  • 如果存在源目录d/vendor,则在根据子树的子树中编译源文件时d,import "p"将其解释为import "d/vendor/p"存在.
  • 当存在多种可能的分辨率时,最具体(最长)的路径获胜.
  • 必须始终使用简短形式:没有导入路径可以/vendor/显式包含" ".
  • 在vendored包中忽略导入注释.

2016年1月更新:Go 1.6将使默认销售.
正如文章"最开始使用GO15VENDOREXPERIMENT的工具"中所详述的那样:

1.6 /vendor/开箱即用支持大多数工具(如oracle); 使用Beta重建它们.


Von*_*onC 9

2018年8月更新:现在使用Go 1.11和模块实现此功能(下面介绍的vgo).

3年后的2018年2月更新.

Russ Cox开发了一种来自核心Golang开发团队的新方法.

VGO项目.

go get -u golang.org/x/vgo
Run Code Online (Sandbox Code Playgroud)

这个提议:

  • 保持最好的部分go get,
  • 增加可重复的构建,
  • 采用语义版本控制,
  • 消除了装修,
  • 弃用GOPATH以支持基于项目的工作流程,以及
  • 提供从其dep及其前身的平滑迁移路径.

vgo semver

它基于新的MVS("最小版本选择")算法:

https://research.swtch.com/version-select-2.png

你可以看到:


2018年5月:Artifactory 提出了一个vgo代理

最近发布的Artifactory 5.11增加了对vgo兼容的Go注册表(以及代理)的支持,在使用Go进行开发时为社区提供了各种功能.
以下是其中一些:

  • Artifactory中的本地存储库允许您根据项目或开发团队为程序包设置安全的私有Go注册表,并具有细粒度的访问控制.
  • 一个远程仓库中Artifactory的是缓存代理进行远程访问的资源,如GitHub的项目.通过Artifactory访问go代理会消除您对网络或GitHub的依赖性,因为Go构建所需的所有依赖项都缓存在Artifactory中,因此在本地可用.这也消除了某人变异或从版本控制中删除依赖关系的风险,或者更糟糕的是,强制推动对远程Git标记的更改,从而改变应该是不可变版本,这可能会为依赖项目造成很多混乱和不稳定.
  • 一个虚拟存储库汇集本地和远程转到注册表让您访问需要为您构建从单一的URL,隐藏了使用本地和远程资源的组合的复杂性都走资源.