如果你想要可重复的构建而无需依赖外部服务(例如模块镜像)或连接到网络,vendor可以提供解决方案。

vendor还有其他好处:

  • 如果从VCS中删除了依赖,或者代理服务器丢失了模块,vendor可以解决。
  • 升级依赖时你可以看见差异对比,并且你可以维护历史记录。
  • 你将能够跟踪和调试依赖,并在必要时进行测试更改。
  • 运行go mod tidygo mod vendor之后,你的更改将被替换。

在本文中,我将提供Go支持vendor的历史以及随着时间的推移默认行为的变化。我还将分享Go的工具如何保持版本之间的向后兼容性。最后,我将分享(随着时间的推移)可能需要手动升级go.mod文件中列出的版本,以更改将来的Go版本的默认行为。

运行不同版本的Go

为了向你展示Go 1.13和Go 1.14之间默认行为的差异,我需要能够同时在我的计算机上运行两个版本的go tooling。发布本文时,我已经在计算机上安装了Go 1.14.2。但是,对于本文,我还需要运行Go 1.13环境。那么如何在不破坏当前开发环境的情况下做到这一点呢?

幸运的是,Go团队发布了版本下载,为你要使用的任何Go版本包括Go Tip提供了特定的二进制文件。

图1

图1显示了来自Go 1.13.10 下载页面的屏幕截图。它显示了构建二进制文件的说明,该二进制文件可用于使用Go 1.13.10构建和测试你的Go代码。

代码1

$ cd $HOME
$ go get golang.org/dl/go1.13.10OUTPUT
go: downloading golang.org/dl v0.0.0-20200408221700-d6f4cf58dce2
go: found golang.org/dl/go1.13.10 in golang.org/dl v0.0.0-20200408221700-d6f4cf58dce2$ go1.13.10 downloadOUTPUT
Downloaded   0.0% (    14448 / 121613848 bytes) ...
Downloaded   9.5% ( 11499632 / 121613848 bytes) ...
Downloaded  30.8% ( 37436528 / 121613848 bytes) ...
Downloaded  49.2% ( 59849840 / 121613848 bytes) ...
Downloaded  69.3% ( 84262000 / 121613848 bytes) ...
Downloaded  90.3% (109804656 / 121613848 bytes) ...
Downloaded 100.0% (121613848 / 121613848 bytes)
Unpacking /Users/bill/sdk/go1.13.10/go1.13.10.darwin-amd64.tar.gz ...
Success. You may now run 'go1.13.10'$ go1.13.10 versionOUTPUT
go version go1.13.10 darwin/amd64$ go versionOUTPUT
go version go1.14.2 darwin/amd64

代码1显示了在Go 1.1.3.10版本运行go get命令并下载完成后的效果,现在我可以在我的机器上使用Go 1.13.10,而扰乱Go 1.14.2的安装。

如果要从计算机中删除Go的任何版本,可以在GOPATH/bin文件夹中找到特定的二进制文件,所有支持文件都可以在HOME/sdk中找到。

代码2

$ cd $GOPATH/bin
$ lOUTPUT
-rwxr-xr-x   1 bill  staff   7.0M Apr 11 10:51 go1.13.10
-rwxr-xr-x   1 bill  staff   2.3M Jan  6 11:02 gotip$ cd $HOME
$ l sdk/OUTPUT
drwxr-xr-x  22 bill  staff   704B Apr 11 10:52 go1.13.10
drwxr-xr-x  24 bill  staff   768B Feb 26 01:59 gotip

Vendoring 快速教程

Go工具出色地将管理应用程序项目的依赖项的工作流程最小化。它需要两个命令:tidy和vendor。

代码3

$ go mod tidy

代码3显示的tidy,帮助保持模块文件中列出的依赖关系准确。一些编辑器(例如VS Code和GoLand)提供了在开发过程中更新模块文件的支持,但这并不意味着一旦你完成所有工作,模块文件会被准确地清理干净。建议tidy你在提交并将任何代码推向VCS之前运行此命令。

如果您还想提供这些依赖项,请在之后运行vendor命令tidy。

代码4

$ go mod vendor

代码4显示了vendor命令。此命令会在项目内部创建一个vendor文件夹,其中包含项目构建和测试代码所需的所有依赖项(直接和间接)的源代码。该命令最好在运行tidy后运行,以使vendor文件夹与模块文件保持同步。确保提交并将vendor文件夹推送到你的VCS。

GOPATH或模块模式

在Go 1.11中,被称为“模块模式”的新模式添加到了Go工具中。当Go工具在模块模式下运行时,会使用模块系统查找和构建代码。当Go工具在GOPATH模式下运行时,传统的GOPATH系统将继续用于查找和构建代码。我使用Go工具的最大难题之一就是不知道不同版本之间默认使用哪种模式,以及需要知道进行哪些配置更改和使用哪些标记,以使构建保持一致。

要了解过去4个版本的Go的历史和语义变化,最好对这些模式进行一下复习。

Go1.11

引入了一个新的环境变量GO111MODULE,其默认值为auto。此变量将根据代码所在的位置(GOPATH的内部或外部)确定Go工具将使用模块模式还是GOPATH模式。要强制使用一种模式,你可以将此变量设置为on或off。对于vendor文件夹,默认情况下,模块模式将忽略vendor文件夹,并针对模块缓存建立依赖关系。

Go1.12

GO111MODULE保留默认设置,并且Go工具继续根据代码所在的位置(GOPATH的内部或外部)确定模块模式或GOPATH模式。对于vendor文件夹,默认情况下,模块模式仍将忽略vendor文件夹,并针对模块缓存建立依赖关系。

Go1.13

GO111MODULE默认设置仍保留,但Go工具不再对工作目录是否在GOPATH中敏感。默认情况下,模块模式仍将忽略供vendor文件夹,并针对模块缓存建立依赖关系。

Go1.14

GO111MODULE保留的默认设置auto,Go工具仍然不再对工作目录是否在GOPATH中敏感。但是,如果存在vendor文件夹,则默认情况下将使用它来构建依赖关系,而不是模块缓存[1]。另外,go命令会确认项目的vendor/modules.txt文件与其go.mod文件保持一致。

版本之间的向后兼容性

在Go 1.14中,默认情况下在模块缓存上使用vendor文件夹更改。最初,我认为我可以只使用Go 1.14来针对现有项目进行构建,这样就足够了,但是我错了。在我使用Go 1.14进行首次构建之后,没有注意vendor文件夹,我了解到Go工具会读取go.mod文件以获取版本信息,并保持与所列版本的向后兼容性。我不知道,但是在Go 1.14的发行说明中清楚地表达了这一点。

https://golang.org/doc/go1.14#go-command

当主模块包含顶级vendor目录并且其go.mod文件指定Go 1.14或更高版本时,go命令现在默认-mod=vendor

为了使用新的默认行为进行vendor管理,我需要将go.mod文件中的版本信息从Go 1.13 升级到Go 1.14。

示范

为了向你展示Go 1.13和Go 1.14的行为,以及Go工具如何保持向后兼容性,我将使用service项目。我将向你展示更改go.mod中列出的版本,Go工具的默认行为如何表现。

首先,我将在GOPATH之外克隆service项目。

代码5

$ cd $HOME/code
$ git clone https://github.com/ardanlabs/service
$ cd service
$ code .

代码5显示了用于克隆项目并使用VS Code打开项目的命令。

代码6

$ ls -l vendor/OUTPUT
total 8
drwxr-xr-x   3 bill  staff    96 Mar 26 16:01 contrib.go.opencensus.io
drwxr-xr-x  14 bill  staff   448 Mar 26 16:01 github.com
drwxr-xr-x  20 bill  staff   640 Mar 26 16:01 go.opencensus.io
drwxr-xr-x   3 bill  staff    96 Mar 26 16:01 golang.org
drwxr-xr-x   3 bill  staff    96 Mar 26 16:01 gopkg.in
-rw-r--r--   1 bill  staff  2860 Mar 26 16:01 modules.txt

代码6显示了项目的vendor文件夹清单。可以看到一些受欢迎的VCS站点的目录以及多个虚构域名。项目依赖于构建和测试的所有代码都位于vendor文件夹中。

接下来,我将手动将go.mod文件更改回版本1.13。这将向你展示我第一次在该项目中使用Go 1.14时遇到的行为。

代码7

module github.com/ardanlabs/servicego 1.13   // I just changed this from go 1.14 to go 1.13

代码7显示了我对该go.mod文件所做的更改(切换go 1.14go 1.13)。

注意:有一个go mod命令可用于更改go.mod文件中的版本:go mod edit -go=1.14

GO 1.13
在第一个构建中,我将使用Go 1.13.10来构建sales-api应用程序。请记住,go.mod文件将Go 1.13列为该项目的兼容版本。

代码8

$ cd service/cmd/sales-api
$ go1.13.10 clean -modcache
$ go1.13.10 buildOUTPUT
go: downloading contrib.go.opencensus.io/exporter/zipkin v0.1.1
. . .
go: finding github.com/leodido/go-urn v1.2.0

代码8显示了如何进入应用程序的文件夹,清除本地模块缓存,然后使用Go 1.13.10执行构建。注意Go工具如何将所有依赖项下载回我的模块缓存中以构建二进制文件。vendor文件夹被忽略。

为了使Go 1.13认可vendor文件夹,我需要在构建和测试时使用-mod=vendor标志。

代码9

$ go1.13.10 clean -modcache
$ go1.13.10 build -mod=vendorOUTPUT

代码9显示了我现在如何在构建调用中使用-mod=vendor标志。这次,模块缓存未使用缺少的模块重新填充,并且认可了vendor文件夹中的代码。

Go1.14

这次,我将使用Go 1.14.2运行build命令,而不使用-mod=vendor标志。

代码10

$ go clean -modcache
$ go buildOUTPUT
go: downloading github.com/openzipkin/zipkin-go v0.2.2
. . .
go: downloading github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e

代码10显示了使用Go 1.14构建项目时发生的情况。由于该工具使用Go 1.13语义进行操作,因此不认可vendor文件夹。这是因为go.mod文件将Go 1.13列为该项目的兼容版本。当我第一次看到这个时,我感到震惊。这就是我开始调查的原因。

如果我将go.mod文件切换到版本1.14,则Go 1.14工具的默认模式将默认切换为认可vendor文件夹。

清单11

module github.com/ardanlabs/servicego 1.14   // I just changed this from go 1.13 to go 1.14

清单11显示了对该go.mod文件的更改回到1.14。我将再次清除模块缓存,并使用Go 1.14再次运行build命令。

代码12

$ go clean -modcache
$ go buildOUTPUT

代码12显示,这次go build使用Go 1.14 的调用中没有重新填充模块缓存。这意味着不需要-mod=vendor标记就可以认可vendor文件夹。由于模块文件列出了Go 1.14,因此默认行为已更改。

vendor和模块的未来变化

感谢John Reese,这里是一个链接的讨论,该讨论基于go.mod文件中列出的内容维护在不同版本的Go之间的向后兼容性。John在帮助验证了本文内容准确和流程正确。

https://github.com/golang/go/issues/30791

将来的发行版中将提供更多有关vendor的支持。讨论中的这样一种功能是关于验证vendor文件夹中的代码以查找代码已更改的情况。

https://github.com/golang/go/issues/27348

我必须感谢Chris Hines提醒我有关Go早期版本中的默认行为以及每个新发行版中的默认行为。Chris还提供了一些有趣的链接,这些链接共享了Go工具中用于模块的一些历史和其他有趣的东西。克里斯在确保职位准确和流程正确方面发挥了作用。
https://github.com/golang/go/issues/33848
https://github.com/golang/go/issues/36460

结论

这篇文章是令我惊讶的是,go.mod中列出的版本影响了Go工具的默认行为。为了获得我想要的Go 1.14中新的默认vendor行为,我必须手动将go.mod列出的版本从1.13 升级到1.14。

对于go.mod使用版本信息来保持版本之间的向后兼容性,我尚未想到任何具体的意见。Go工具从未与Go兼容性的承诺挂钩,因此这对我来说是意想不到的。也许这是伟大事物的开始,并且Go工具可以不断发展,而Go社区不必担心发布新版Go工具时其构建,测试和工作流程是否会中断。

如果你有任何意见,我很想在Twitter上听听的意见。

补充说明

[1]从Go 1.11开始,该-mod=vendor标志使go命令从vendor目录而不是从模块缓存中加载模块。(vendor目录包含单个软件包,而不是完整的模块。)在Go 1.14中,该-mod标志的默认值根据主模块的内容而变化:如果存在vendor目录且go.mod文件指定go 1.14或更高,则-mod默认为-mod=vendor。如果go.mod文件是只读的,则-mod默认为-mod=readonly。我们还添加了一个新值-mod=mod,意思是“从模块缓存中加载模块”(也就是说,如果没有其他条件满足,则默认情况下会获得相同的行为)。即使你正在使用默认行为的主模块-mod=vendor,你可以使用该-mod=mod标志显式返回模块缓存。-Bryan Mills

Vendor使用:golang的vendor是个啥?相关推荐

  1. openharmony编译报错ubuntu20.04按照官方文档,hb set报错为OHOS ERROR] Invalid vendor path: /home/openharmony/vendor

    ubuntu20.04按照官方文档,hb set报错为OHOS ERROR] Invalid vendor path: /home/openharmony/vendor 作者:坚果 公众号:" ...

  2. golang编译之vendor机制

    原文地址:golang编译之vendor机制 Go 1.5引入了vendor 机制,但是需要手动设置环境变量 GO15VENDOREXPERIMENT= 1,Go编译器才能启用.从Go1.6起,,默认 ...

  3. golang vendor介绍

    vendor 简介 vendor是golang的一个包管理器.开启包管理器,需要一个环境变量的支持,且golang sdk 版本必须大于1.5 export GO15VENDOREXPERIMENT= ...

  4. go build不从本地gopath获取_Go包管理GOPATH、vendor、go mod机制

    简介 Golang 作为开源编程语言,在 2012 年编程语言 Go 1 发布之后,一直在不断发展,并伴随着云原生而广泛进入各大公司. 在互联网发展至今,软件系统不断膨胀. 各个编程语言也都逐步支持了 ...

  5. vendor自动恢复_解决 vendor 中存在大小写变更问题

    前言 go mod (vendor) 是 golang 中依赖管理的一个工具,而 git 是个版本管理工具,两者结合本该是相得益彰事情,然而在某些情况下并不是如此 在某个项目中,需要更新 k8s.io ...

  6. linux go vendor目录,Go 包依赖管理工具 —— govendor

    govendor 是一个基于 vendor 机制实现的 Go 包依赖管理命令行工具.与原生 vendor 无侵入性融合,也支持从其他依赖管理工具迁移,可以很方便的实现同一个包在不同项目中不同版本.以及 ...

  7. 什么是 go vendor

    go vendor 是golang引入管理包依赖的方式,1.5版本开始引进,1.6正式引进. 基本原理 其实就是将依赖的包,特指外部包,复制到当前工程下的vendor目录下,这样go build的时候 ...

  8. 【Go】Go 包管理 之 Go Vendor

    文章目录 一.包管理历史 二.vendor 机制的进步 三.Go Vendor 参考链接 一.包管理历史 Golang 的包管理一直被大众所诟病的一个点,但是我们可以看到现在确实是在往好的方向进行发展 ...

  9. go vendor 项目迁移到 mod 项目

    检查最新的 Golang 版本 你如果问我,为什么要用最新的?因为我们都是软件爱好者,我们应该渴望测试最新的技术! ( 顺便说一下,你可以用 Golang 1.11.X,但是您应该想知道为什么不使用最 ...

  10. go vendor介绍

    go vendor是golang引入管理包依赖的方式,1.5版本开始引进,1.6正式引进. 基本原理 其实就是将依赖的包,特指外部包,复制到当前工程下的vendor目录下,这样go build的时候, ...

最新文章

  1. 持久性session连接之memcached高可用方案
  2. Frighting的日常:第6天
  3. 设计模式-结构型-桥接
  4. oracle停止trace日志,关闭ORACLE客户端trace日志
  5. python 导入csv文件到oracle_python将文件夹下的所有csv文件存入mysql和oracle数据库
  6. mysql rpm 启动_MySQL安装(rpm)和启动配置
  7. sql server中存储过程提示错误
  8. 《Spring Recipes》第二章笔记:Customizing Bean Initiali...
  9. Xshell连接mysql数据库乱码问题解决思路总结
  10. 代码健壮性 —— 异常保护和合法性检测
  11. 粒子滤波算法理解及实现
  12. 图像标注工具python+opencv
  13. ORA-12170:TNS:连接超时错误处理
  14. 样本均值的抽样分布/置信区间
  15. 游戏推广中买量和导量是什么意思?
  16. 建立dblink(database link)
  17. 数字图像处理,自适应中值滤波的C++实现
  18. 中国家具行业投资竞争力分析与市场营销策略报告2022-2028年
  19. 问题是:有一只奶牛,出生后第四年成熟,成熟后每年生一只奶牛,问20年后有多少只奶牛?
  20. 《第一堂棒球课》:王牌中外野·棒球8号位

热门文章

  1. 夏夜也发低烧—夜的精灵[风潮唱片]
  2. u盘安装centos8黑屏_求助啊为何装centos7一点安装就黑屏
  3. Kubernetes:(十四)安全机制(一定要做好安全措施哦)
  4. ​软考高项论文写作这些雷区,千万要避开
  5. 【重要】国庆节快乐!有三AI所有课程限时7天优惠
  6. UDE2021未来生活领袖峰会:视像行业发展趋势研究报告发布
  7. emoji表情 mysql转移,mysql中emoji表情存储
  8. Qt Creator 的下载与安装
  9. 阿里云EMAS移动测试|快速掌握移动端兼容性测试技巧
  10. oracle 格式化命令,format 命令的输入规则 - Oracle Solaris 管理:设备和文件系统