失宠的Vendor目录
Vendor目录是Golang从1.5版本开始引入的,为项目开发提供了一种离线保存第三方依赖包的方法。但是到了Golang 1.11之后,由于引入了Module功能,在运行go build时,优先引用的是Module依赖包的逻辑,所以Vendor目录就被“无视”了,进而可能会发生以下编译错误(中间一个是因为当前的GOPATH不对,这是个伏笔):
Module说,还是很想他
上篇文章提到过go mod
有很多子命令,其中就有个go mod vendor
命令,运行试试,不出意外地报错了:
报错信息说找不到main module,应该是每次使用module功能都得先go mod init
一把,那么试试go mod init github.com/nevermosby/mydocker
,结果令人惊奇:
go mod init
命令竟然是respectGodep
功能的!!!来看看生成的go.mod文件:
对比Godep.json原文件相关内容:
发生了以下映射关系:
Deps变成了require
ImportPath内容被沿用下来,毕竟是依赖包名称
Comment被直接舍弃了,
Nice to have
的东西一般都是这个下场v0.0.0-20151204141443-446d1c146faa,这段很有趣,v0.0.0是为了符合
go module
版本控制的规范做的workround; 20151204141443-446d1c146faa是代表了这个依赖包当初被引入时最新一次commit的时间和hash值(取了前12位),应该是通过Rev这个commit反查出来的
这么看来,Godep作为Dependency tools for go的前身,相比go vendor
,与go module
还是更近一点。那实在喜欢go vendor
的我们该如何是好?
Module说,那我们重新开始
还记得刚开始执行的go mod vendor
命令么,让我们再试试。。。这次运行完毕没有任何报错了,所以他们俩终于“有情人终成眷属”了?!有疑问找help文档:
帮助文档告诉我们,这个操作的本质是把原有vendor目录里的内容,reset
成当前程序所需的全部依赖包,即把执行go mod init
后下载的相关依赖包(都被下载到了GOPATH
的pkg
目录)全部复制到原有vendor目录下了,通过git status
可以证明这件事情:
不难发现,原有vendor目录里的依赖包内容发生了改变,选一个看看diff
:
是权限发生了改变,可以侧面证明文件有被覆盖更新的痕迹。
终于真相大白了,要跟go module
重新开始的前提,就是你得先变成他喜欢的样子。。。
好日子终于要开始了?
来吧,试试go build
能否成功,这次咱们长个心眼,提前看看帮助文档里有没有与go module
相关的内容。。。果不其然,有个可选参数:
go build -mod=vendor
运行试试。。。编译成功了,生成了可执行文件,运行它,结果符合期待。。。
你是不是跟我一样,发现了不得了的事情了,联系文章开头的伏笔,发现了通过go module
机制,编译go语言项目竟然可以不用指定GOPATH
了。
使用这个命令,让官方告诉你modules本质意义
客观上,从事物持续发展的眼光看这个问题,回答一定是yes!
那么主观上,怎么让自己信服呢?运行下面的命令,来看Golang官方的解释:
令人惊奇的是,Google竟然把洋洋洒洒近2万个单词组成的文章,塞进了帮助文档里,不知道算不算彩蛋。上面只是摘取了部分文字,如果大家感兴趣,可以到这个 gist 看全文。
从上面摘取的第一段文字来看Module
的设计定位:
在Go项目扮演着包管理员的角色
是源代码互相通信和版本管理的单元
会被
go
命令行工具强烈支持基于
GOPATH
的编译方案将被其取代
因此,官方其实已经下了决心,要大力推广Go Module概念了,大家收拾收拾,可以重新站队了。
PS:官网文档里其实还有这么一段:
If GO111MODULE=off, then the go command never uses the new module support. Instead it looks in vendor directories and GOPATH to find dependencies; we now refer to this as “GOPATH mode.”
所以,让Module Respect Vendor 最简单的方法,就是设置环境变量GO111MODULE为off。