Vendor使用:golang的vendor是个啥?
如果你想要可重复的构建而无需依赖外部服务(例如模块镜像)或连接到网络,vendor可以提供解决方案。
vendor还有其他好处:
- 如果从VCS中删除了依赖,或者代理服务器丢失了模块,vendor可以解决。
- 升级依赖时你可以看见差异对比,并且你可以维护历史记录。
- 你将能够跟踪和调试依赖,并在必要时进行测试更改。
- 运行
go mod tidy
,go 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.14
为go 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是个啥?相关推荐
- 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 作者:坚果 公众号:" ...
- golang编译之vendor机制
原文地址:golang编译之vendor机制 Go 1.5引入了vendor 机制,但是需要手动设置环境变量 GO15VENDOREXPERIMENT= 1,Go编译器才能启用.从Go1.6起,,默认 ...
- golang vendor介绍
vendor 简介 vendor是golang的一个包管理器.开启包管理器,需要一个环境变量的支持,且golang sdk 版本必须大于1.5 export GO15VENDOREXPERIMENT= ...
- go build不从本地gopath获取_Go包管理GOPATH、vendor、go mod机制
简介 Golang 作为开源编程语言,在 2012 年编程语言 Go 1 发布之后,一直在不断发展,并伴随着云原生而广泛进入各大公司. 在互联网发展至今,软件系统不断膨胀. 各个编程语言也都逐步支持了 ...
- vendor自动恢复_解决 vendor 中存在大小写变更问题
前言 go mod (vendor) 是 golang 中依赖管理的一个工具,而 git 是个版本管理工具,两者结合本该是相得益彰事情,然而在某些情况下并不是如此 在某个项目中,需要更新 k8s.io ...
- linux go vendor目录,Go 包依赖管理工具 —— govendor
govendor 是一个基于 vendor 机制实现的 Go 包依赖管理命令行工具.与原生 vendor 无侵入性融合,也支持从其他依赖管理工具迁移,可以很方便的实现同一个包在不同项目中不同版本.以及 ...
- 什么是 go vendor
go vendor 是golang引入管理包依赖的方式,1.5版本开始引进,1.6正式引进. 基本原理 其实就是将依赖的包,特指外部包,复制到当前工程下的vendor目录下,这样go build的时候 ...
- 【Go】Go 包管理 之 Go Vendor
文章目录 一.包管理历史 二.vendor 机制的进步 三.Go Vendor 参考链接 一.包管理历史 Golang 的包管理一直被大众所诟病的一个点,但是我们可以看到现在确实是在往好的方向进行发展 ...
- go vendor 项目迁移到 mod 项目
检查最新的 Golang 版本 你如果问我,为什么要用最新的?因为我们都是软件爱好者,我们应该渴望测试最新的技术! ( 顺便说一下,你可以用 Golang 1.11.X,但是您应该想知道为什么不使用最 ...
- go vendor介绍
go vendor是golang引入管理包依赖的方式,1.5版本开始引进,1.6正式引进. 基本原理 其实就是将依赖的包,特指外部包,复制到当前工程下的vendor目录下,这样go build的时候, ...
最新文章
- 持久性session连接之memcached高可用方案
- Frighting的日常:第6天
- 设计模式-结构型-桥接
- oracle停止trace日志,关闭ORACLE客户端trace日志
- python 导入csv文件到oracle_python将文件夹下的所有csv文件存入mysql和oracle数据库
- mysql rpm 启动_MySQL安装(rpm)和启动配置
- sql server中存储过程提示错误
- 《Spring Recipes》第二章笔记:Customizing Bean Initiali...
- Xshell连接mysql数据库乱码问题解决思路总结
- 代码健壮性 —— 异常保护和合法性检测
- 粒子滤波算法理解及实现
- 图像标注工具python+opencv
- ORA-12170:TNS:连接超时错误处理
- 样本均值的抽样分布/置信区间
- 游戏推广中买量和导量是什么意思?
- 建立dblink(database link)
- 数字图像处理,自适应中值滤波的C++实现
- 中国家具行业投资竞争力分析与市场营销策略报告2022-2028年
- 问题是:有一只奶牛,出生后第四年成熟,成熟后每年生一只奶牛,问20年后有多少只奶牛?
- 《第一堂棒球课》:王牌中外野·棒球8号位
热门文章
- 夏夜也发低烧—夜的精灵[风潮唱片]
- u盘安装centos8黑屏_求助啊为何装centos7一点安装就黑屏
- Kubernetes:(十四)安全机制(一定要做好安全措施哦)
- ​软考高项论文写作这些雷区,千万要避开
- 【重要】国庆节快乐!有三AI所有课程限时7天优惠
- UDE2021未来生活领袖峰会:视像行业发展趋势研究报告发布
- emoji表情 mysql转移,mysql中emoji表情存储
- Qt Creator 的下载与安装
- 阿里云EMAS移动测试|快速掌握移动端兼容性测试技巧
- oracle 格式化命令,format 命令的输入规则 - Oracle Solaris 管理:设备和文件系统