Golang依赖管理最佳实践

时间:2015-05-18 10:03:30

标签: go

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

import "github.com/RichardKnop/somelibrary"

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

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

import "github.com/RichardKnop/somelibrary#v1.4.8"

在Go中管理依赖项的最佳做法是什么?

我可以看到两种方法。

予。版本模块

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

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

import "github.com/RichardKnop/somelibrary/v1"

或者:

import "github.com/RichardKnop/somelibrary/v2"

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

II。分叉

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

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

import "github.com/ForkingUser/somelibrary"

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

思想?

4 个答案:

答案 0 :(得分:15)

二月2018年:如果将vgo集成到工具链中,则下面(2015/2016)的出售方法可能最终消失。
请参阅my answer below

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

III。 Vendoring

AFAIK,这是确保您的构建具有可再现性和可预测性的最广泛使用的方法。 Go团队本身uses vendoring在他们的回购中。 Go团队现在讨论统一依赖清单文件格式。来自Go toolchain developers mailing list

  

在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 +中重新评估包括这样的工具。

  •   

答案 1 :(得分:11)

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

请参阅c/10923/

  

GO15VENDOREXPERIMENT=1在环境中时,此CL会根据Go 1.5供应商提案更改导入路径的分辨率:

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

2016年1月更新:Go 1.6将默认销售 详见the article "MOST GO TOOLS NOW WORK WITH GO15VENDOREXPERIMENT"

  

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

答案 2 :(得分:7)

2018年8月更新:现在使用 Go 1.11 and modules 实施此功能(以下显示的vgo)。

更新于2018年2月,3年后。

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

vgo 项目。

go get -u golang.org/x/vgo
  

此提案:

     
      
  • 保留go get
  • 的最佳部分   
  • 添加可重现的构建
  •   
  • 采用语义版本控制,
  •   
  • 消除了售卖
  •   
  • 弃用GOPATH以支持基于项目的工作流程,
  •   
  • 提供了dep及其前身的平滑迁移路径。
  •   

vgo semver

它基于新的MVS ("Minimal Version Selection") algorithm

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

你可以看到:

2018年5月:Artifactory proposes a vgo proxy

  

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

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

答案 3 :(得分:0)

也可以在maven中描述依赖关系,如果要使用mvn-golang-wrapper,如果它在maven中看起来像文本

<plugin>
 <groupId>com.igormaznitsa</groupId>
 <artifactId>mvn-golang-wrapper</artifactId>
 <version>1.1.0</version>
 <executions>
  <execution>
    <id>golang-get</id>
     <goals>
       <goal>get</goal>
     </goals>
     <configuration>
       <packages>
         <package>github.com/gizak/termui</package>
       </packages>
       <buildFlags>
         <flag>-u</flag>
       </buildFlags>
       <goVersion>1.6</goVersion>
     </configuration>
   </execution>
</plugin>