记一次go module的坑

小一过河 · · 15957 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

一、背景

事情是这样的,因为小马本次要写一个go项目。但是因为一些权限问题,一些依赖包在内网小马获取不到,于是只能求助大大。大大给的策略就是他先把所有的依赖包go mod,然后go mod vendor迁移到项目目录vendor下进行本地依赖载入即可,也就是使用 go build -mod=vendor来编译即可。一切似乎看起来还是那么完美。然后正要起飞,直接翻车,现场如下。【这里插播一条发现,就是使用golang IDE go build 和使用命令行go build 的区别在于前者不会生成.exe文件】

二、翻车现场

将大大go mod vendor完的包pull到本地,只要编译就会发生如下错误(以下省略了一部分类似的报错)。其实是 go.mod内的所有依赖包都报错。

dD:\Go\bin\go.exe build -o C:\Users\lihi\AppData\Local\Temp\___go_build_main_go.exe D:\gok\word\main.go #gosetup

go: inconsistent vendoring in D:\gok\word:

git.code.oa.com/components/l5@v0.3.0: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt

github.com/golang/protobuf@v1.4.3: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt

golang.org/x/net@v0.0.0-20201216054612-986b41b23924: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt

run 'go mod vendor' to sync, or use -mod=mod or -mod=readonly to ignore the vendor directory

Compilation finished with exit code 1

三、现场勘察

大大说他的本地编译是正常的。不得不怀疑是不是因为大大本地gopath还有一份包依赖的原因,然而经查并不是这个问题。翻阅了网络上的大部分资料无果,网络上要么是说是因为识别不到包,按照提示重新go mod vendor一下就可以了。小马蛮试了一下,不出所料必然地报远程报获取不到呢,IDE的报错定位其实是不准确的。再次检查vendor/modules.txt文件,没有问题,无果。 于是开始质疑golang IDE 的版本支持问题,无果。看了下go.mod文件中写着go 1.14,也没错呢,小马用的GO SDK正是1.14.4版本。敲出go env 查看环境配置,GO111MODULE=on,因为环境变量是auto,但是go到一定版本后默认是on,也没问题,无果。那问题出在哪呢?由于没有依赖包拉取权限,只能再次求助大大,大大表示也很奇怪,一番折腾,于是问题得到解决。【这里插播一条好玩的东西,就是GO111MODULE为什么是GO111呢,因为其实1.11版本开始支持MODULE的】

四、问题解决

结论是:因为大大go  mod的时候用的是go 1.13,而我编译的时候用的 1.14,所以就报了这个奇怪的错误。you what?直接懵逼。但是为啥go.mod文件中写的版本要求是1.14,而大大用1.13也编译得好好的。

这是个大坑,掉进坑里自己扑腾了一天!!希望大家谨慎入坑。

五、小本本

爬坑一小时出坑一秒钟,每一次的爬坑都是充满着十八般绝技。奇怪的姿势又增加了。

go运行方式有哪几种?

gopath模式, 配置gopath目录,一般目录下有三个目录:bin,pkg,src。项目代码放在src中。先在gopath的vendor中寻找依赖包。

go mod模式, 是先在项目目录的vendor下寻找依赖包,然后在gopath的pkg/mod下寻找依赖包。如果都没有则远程下载到默认gopath的pkg/mod下,该模式不认src目录。也可以强制用go build -mod=vendor 或者-mod=mod来决定是否直接使用本地的vendor依赖包直接运行编译,忽略go mod中的依赖,不识别远程依赖包(这一点非常适合包的随意拷贝分发,当然也是本次没有依赖包权限的解决方法)。

如果GO111MODULE是auto则根据项目目录位置和是否含有go.mod文件来决定使用什么模式。如果是GO111MODULE=off则使用gopath,如果是on则使用module模式。gopath模式下的src目录下不能有go.mod文件,否则报错。

一些go mod命令记录备用,国内的资料并不多(注意go mod 命令在 $GOPATH 里默认是执行不了的,因为 GO111MODULE 的默认值是 auto。默认在$GOPATH 里是不会执行, 如果一定要强制执行,就设置环境变量为 on。):

查看环境设置:go env

查看go版本:go version

设置顶级vendor作为依赖:go env -w GOFLAGS="-mod=vendor"  查看env 是GOFLAGS=-mod=vendor,取消:g o env -w GOFLAGS="-mod=";

指定gomod编译 模式:go build -mod=vendor

go mod download下载模块到本地缓存,缓存路径是$GOPATH/pkg/mod/cache

go mod edit是提供了命令版编辑go.mod的功能,例如go mod edit -fmt go.mod会格式化go.mod

go mod graph把模块之间的依赖图显示出来

go mod init初始化模块(例如把原本dep管理的依赖关系转换过来)

go mod tidy增加缺失的包,移除没用的包

go mod vendor把依赖拷贝到vendor/目录下

go mod verify确认依赖关系

go mod why解释为什么需要包和模块


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:小一过河

查看原文:记一次go module的坑

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

15957 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传