记一次go module的坑

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

一、背景

事情是这样的,因为小马本次要写一个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文件,否则报错。
image.png

一些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解释为什么需要包和模块

相关文章
|
3月前
|
存储 Linux Go
GO 项目依赖管理:go module总结
GO 项目依赖管理:go module总结
52 0
|
29天前
|
存储 Go
Golang语言基于go module方式管理包(package)
这篇文章详细介绍了Golang语言中基于go module方式管理包(package)的方法,包括Go Modules的发展历史、go module的介绍、常用命令和操作步骤,并通过代码示例展示了如何初始化项目、引入第三方包、组织代码结构以及运行测试。
31 3
|
2月前
|
IDE Go 开发工具
Go Error module declares its path as but was required as解决方案
文章提供了一个解决方案,用于处理在Go工程中将依赖的仓库从A更换为B(即使它们完全相同)时遇到的路径声明错误,建议通过发布新版本来解决此问题。
44 0
|
11月前
|
Go
go: finding module for package
go: finding module for package
|
存储 缓存 Go
为什么应该使用 Go module proxy
为什么应该使用 Go module proxy
143 0
|
Go
【golang】解决:missing go.sum entry for module providing package
【golang】解决:missing go.sum entry for module providing package
1451 0
go module的使用:
go module的使用:
118 0
|
存储 算法 Go
Go的Module不会,证明你实力就那样吧
Go的Module不会,证明你实力就那样吧
|
Go API 开发工具
Go Module 语义化版本规范
Go Module 语义化版本规范
119 0
go语言module,依赖管理方法
1.为什么需要依赖管理 最早的时候,Go所依赖的所有的第三方库都放在GOPATH这个目录下面。这就导致了同一个库只能保存一个版本的代码。如果不同的项目依赖同一个第三方的库的不同版本,应该怎么解决? go module是Go1.11版本之后官方推出的版本管理工具,并且从Go1.13版本开始,go module将是Go语言默认的依赖管理工具
180 0
go语言module,依赖管理方法