Golang依赖管理之dep

讲解Golang依赖管理工具dep的使用,It's not the last one,though.

Posted by TopJohn on 2019-01-27
本文总阅读量

Golang依赖管理之dep

dep是一个Golang的依赖管理工具,曾经有望成为Golang官方的依赖管理工具。

项目介绍

dep是一个Golang的依赖管理工具。它要求用Go 1.9或者更高版本来编译。

dep是一个“官方的试验”。正如Go 1.11的到来,Go的工具链已经试验性地采用了一种大幅剥离dep的方法。作为结果,我们将继续开发dep,但是整体工作主要还是指向开发Go工具链中的替代原型为主(这里指的是Go 1.11的go modules的一个竞争对手,新的dep)。

安装

强烈推荐你使用release版本。Release的二进制在release页中可以下载。

在MacOS中你可以采用Homebrew安装或者更新release的版本:

1
2
$ brew install dep
$ brew upgrade dep

在其他操作系统上你可以采用install.sh脚本进行安装:

1
$ curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh

install.sh脚本会默认将其安装在$GOPATH/bin目录中,或者 你可以设置特殊的环境变量INSTALL_DIRECTORY来改改变安装路径。

如果你的操作系统是install.sh脚步不支持的,你需要手动构建它或者通知开发团队将你对应的操作系统加入到release列表中。

如果你是一名极客,对dep感兴趣的话,你可以通过go get来安装:

1
go get -u github.com/golang/dep/cmd/dep

宣布dep v0.5.0

dep v0.5.0在2018年7月25日发布。

这次发布最大的主题是性能的提升。dep最初是以安全性为基调设计的,因为基金会后期会提相关dep性能上的事。现在它有了。

注意: 你的整个团队都需要立刻更新这个release,因为这次更新导致旧版本的dep将无法识别Gopkg.lock文件。

性能的提升

主要在2个方面有了性能的提升:

  1. 元数据的缓存
  2. vendor的校验

元数据的缓存是一个实验性的特性,缓存了解析以及代码分析的部分过程,包括:读取Gopkg.toml文件以及解析.go文件中的import声明等。这些工作以及git checkout将代码放到磁盘上分析正是解决者之前在一直努力的事。

当缓存开启的时候(通过环境变量DEPCACHEAGE管理),访问的项目和版本的组合将会从原来的缓存中取出。每个处理步骤下降到(亚)毫秒级别;之前是几百毫秒或者秒级的范围。

Vendor校验需要Gopkg.lock包含足够多的信息,以便能够去校验Vendor/目录是否是它们应该有的样子,包括你设置的修剪参数。通过添加digestpruneoptsGopkg.lock文件的每个[[project]]节里,现在已经完成了这个特性。

目前已经不需要在dep ensure阶段重写整个Vendor/目录了,这个方面性能提升了。代替的是,dep选择性地重新覆盖或者移除那些必须修改Vendor/目录的文件信息到Gopkg.lock。通过-v参数,你可以看到具体的变化信息:

1
2
3
4
5
# Bringing vendor into sync
(1/4) Wrote github.com/eapache/go-resiliency@v1.1.0: version changed (was v1.0.0)
(2/4) Wrote github.com/gregjones/httpcache@master: revision changed (2bcd89a174 -> 9cad4c3443)
(3/4) Wrote github.com/prometheus/common@master: prune options changed (UT -> NUT)
(4/4) Removed unused project github.com/kr/pretty

这些提升通过不同的方式影响到了不同的工作流,代表性的有dep ensure -v运行从120s降到了4s(包括计算和更新Vendor/2个过程)

改善的反馈

Vendor校验除了在性能上还有其他的含义。随着它的完善,修复了是否所有依赖信息无法都在你的项目里的最后的盲点-代码中的importsGopkg.tomlGopkg.lock,以及vendor/-保持同步。这能保证不仅粗粒度的vendor/目录反馈,也能告诉你项目中具体哪些不同步的地方正在被解决。

在过去,dep告诉你了这件事,但是有点无用,并没有指出具体信息:

1
2
$ dep ensure -update -v
Warning: Gopkg.lock is out of sync with Gopkg.toml or the project's imports.

并不是很有用。

但是,现在,如果dep ensure -v在项目中发现了不同步的问题,需要重新构建,它会告诉你确切的原因:

1
2
3
4
5
$ dep ensure -v
# Gopkg.lock is out of sync
github.com/kr/pretty: imported or required, but missing from Gopkg.lock's input-imports
github.com/aws-sdk-go/aws/awserr: in Gopkg.lock's input-imports, but neither imported nor required
github.com/pkg/errors@v0.7.0: not allowed by constraint ^0.8.0

当然,如果你只想知道什么不同步了,但是不需要改变?有新的子命令满足你的需求。

dep check

这次release介绍了新的命令,dep check,报告了所有项目中不同步的信息。包括了dep ensure -v命令,但是也展示相关的vendor目录的问题:

zhi
1
2
3
4
5
6
7
8
9
$ dep check
# Gopkg.lock is out of sync
github.com/kr/pretty: imported or required, but missing from Gopkg.lock's input-imports
github.com/aws-sdk-go/aws/awserr: in Gopkg.lock's input-imports, but neither imported nor required
github.com/pkg/errors@v0.7.0: not allowed by constraint ^0.8.0

# vendor is out of sync
github.com/pkg/errors: missing from vendor
github.com/aws-sdk-go/aws: hash of vendored tree not equal to digest in Gopkg.lock

dep check也是为自动化工具设计的:

  • 如果检查失败了会返回1.为了最大程度自动化效用,通过-q会压缩任何输出。
  • 操作是很快的;默认情况下它的检查不访问网络。通过磁盘的人缓存,它会在几秒内完成一个大项目的检索。
  • 不会访问网络,是它快的原因。一个非常大的项目可以通过它来作为一个预提交钩子:

你可以使用它来作为预提交狗子,来保证你的提交依赖都是同步的。下述命令将会设置:

1
2
3
4
5
cat >.git/hooks/pre-commit <<EOL
#!/bin/bash
dep check
EOL
chmod +x .git/hooks/pre-commit

同样推荐使用dep check在持续集成中。在dep项目本身,通过dep check替换缓慢,信息不明的脚本。

noverify

不幸的是,在某些情况下,你需要对项目中的vendor目录进行修改,但是让上游项目改变他们的方式是不切实际的。代码生成可能是最常见的情况。

在以前版本的dep中,可以通过脚步来内嵌dep ensure,自动地重新应用你的修改。但是,有了vendor校验,dep会将其视为异常状态,dep ensure总是会尝试修复它,而且dep check也将会失败。

为了解决这个问题,dep已经在Gopkg.toml中添加了noverify,你可以提供一系列项目的根到noverify中,这样vendor校验就会对这些进行跳过。dep check任然会打印关于相关问题的信息,以此来保证能够继续追踪到代码同步信息。

1
github.com/aws-sdk-go/aws: hash of vendored tree not equal to digest in Gopkg.lock (CHECK IGNORED: marked noverify in Gopkg.toml)

但是如果这些被忽略的问题是dep发现的唯一的问题,那么它将会返回0。

dep, vgo/modules,和以后

Modules又名vgo,已经被实验性地merge进了go的命令行中,并且会在Go1.11中呈现。Go团队相信这将会消除对dep的需求。(惊恐万分,dep岂不是要为历史献身了)

一方面,我们很高兴Golang开发团队最终认真对待依赖管理问题。而且在vgo中有一些非常有用的想法-在依赖管理问题上的重要贡献,以及一些未来计划中会收益的地方。

但是,我们认为vgo将步伐推动的太快了。为了追求算法的简洁性,它建立了一系列生态规则来让人们遵循,而且给已经很紧张的维护者push了很多不必要的工作。这些设计深深扎根于工具链中,如果不默认启用这些规则将无法使用。

这意味着在“vgo/modules 或者dep”中没有选择。它将是“vgo,或者其他语言”。

这是一个复杂的话题。我们正在努力尝试以更容易理解的方式来解释。

正如dep团队认为的,modules的化身对于Go社区来说是有害的,所以他们将继续dep的开发,为当前构成模块系统基础的版本控制行为开发一个替代原型。为此,dep的下一个版本主要关注点是改善“获取最新的传递依赖”问题。这个问题是dep被批判的基石;自从dep第一次发布,这个问题一直是dep团队的目标。

总结

最新的dep v0.5.0版本最大的特点就是“快”了,其次加入了更详细的过程分析和校验,同时,它并不想放弃争夺Golang官方依赖管理的地位的机会,将会继续完善开发新版本,不到最后谁也不知道go的依赖管理最终会采用哪种机制,博客翻译的有点水,希望以后能够逐渐适应,谢谢各位的观看,下期分享dep的具体使用方法。

本文翻译自下述参考资料: