Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >​从一个模块冲突问题学习go module

​从一个模块冲突问题学习go module

原创
作者头像
王沛文
修改于 2019-04-23 07:04:50
修改于 2019-04-23 07:04:50
12.2K4
举报
文章被收录于专栏:王沛文的专栏王沛文的专栏

问题

最近遇到了一个很诡异的问题,项目中依赖了ginviper之后竟然提示错误

代码语言:txt
AI代码解释
复制
cannot load github.com/ugorji/go/codec: ambiguous import: found github.com/ugorji/go/codec in multiple modules:
        github.com/ugorji/go v1.1.1 (D:\workspace\go\pkg\mod\github.com\ugorji\go@v1.1.1\codec)
        github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8 (D:\workspace\go\pkg\mod\github.com\ugorji\go\codec@v0.0.0-20181204163529-d75b2dcb6bc8)

直接从字面看似乎是符号冲突,类似于C/C++中引入了两个不同的符号,但是go module以后包都是统一放到$GOPATH/pkg下的不应该会出现类似问题。

通过go mod graph可以查看具体依赖路径

代码语言:txt
AI代码解释
复制
github.com/spf13/viper@v1.3.2 github.com/ugorji/go/codec@v0.0.0-20181204163529-d75b2dcb6bc8
github.com/gin-gonic/gin@v1.3.1-0.20190120102704-f38a3fe65f10 github.com/ugorji/go@v1.1.1

可以看到viper和gin分别依赖了github.com/ugorji/gogithub.com/ugorji/go/codec

应该是go把这两个path当成不同的模块引入导致的冲突

这里很奇怪的地方是,为什么github.com/ugorji/go/codec作为一个子目录也会被当成模块引入

分析

到了github.com/ugorji/go上看发现还真有类似的问题

首先我们看一下这个包是干什么的

根据首页描述应该是个处理msgpack编码协议的包,这里有一点值得注意

github.com/ugorji/go仓库根目录并没有文件,所有实现在github.com/ugorji/go/codec

再回头看看这个包的历史,基本可以了解这个问题了

  1. v1.1.1 这个tag时,并没有使用go.mod,因此当使用了go module的包引用github.com/ugorji/go/codec时,go会根据path找到github.com/ugorji/go这个仓库并将其作为一个包引入

这就对应这上面的

代码语言:txt
AI代码解释
复制
   github.com/ugorji/go v1.1.1
  1. e253f1f20942cb6dc505e504e8bbba4b7f434cb2这个提交之后,作者在codec目录下添加了go.mod文件.这时候go就把github.com/ugorji/go/codec作为一个模块,和前面的github.com/ugorji/go认为是两个模块了.这时如果两个包分别使用了这两个版本就会导致上面的问题
  2. v1.1.2 这个tag时作者修复了上面的问题,方法是在codec目录的go.mod下添加了依赖
代码语言:txt
AI代码解释
复制
+ require github.com/ugorji/go v1.1.2

这时候依赖github.com/ugorji/go@1.1.1的老模块和依赖github.com/ugorji/go/codec@1.1.2的新模块一起使用时,由于上面的变更,整个项目里依赖的github.com/ugorji/go模块会使用较新的1.1.2.

因为1.1.2的时候codec目录下已有go.mod,因此github.com/ugorji/go下面不会有任何文件,就不会导致符号冲突

  1. v1.1.4的时候 作者又把codec下的go.mod删除了,而在根目录下新增了go.mod

这时对go来说回到了v1.1.1的时候,如果同时有两个依赖模块依赖v1.1.2和v1.1.4时同样会出现符号冲突的问题

总结

在gopath时代没有版本的概念,大家都在一个gopath下,符号基于路径,因此没有符号冲突的问题

在vendor时代,vendor下的包会被加上$package\vendor前缀,因此项目中不同的包依赖相同模块的不同版本时也不会冲突

到了module时代,所有的依赖包都在$GOPATH/pkg下,虽然存储的时候分了版本,但是链接时并没有,因此任何代码不同版本只有最新的一份.

可能这些描述看着很别扭,我们先整理一下go module中的一些术语:

  • module 模块。有go.mod文件时,则是go.mod文件所在的路径,对于没有go.mod文件的则是仓库根目录
  • package 包。包就是go文件中import的东西,按路径区分

上面的问题本质就是由于作者的疏忽造成了存在两个模块github.com/ugorji/gogithub.com/ugorji/go/codec同时这两个模块又存在相同的包,导致符号冲突

这些问题在golang官方的wiki中都有描述.建议大家在使用go module之前也详细阅读一下官方wiki

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
4 条评论
热度
最新
非常非常感谢
非常非常感谢
回复回复点赞举报
已经好了
已经好了
回复回复点赞举报
及时雨啊,今天刚遇到
及时雨啊,今天刚遇到
11点赞举报
怎么解决啊,本地怎么配置啊?
怎么解决啊,本地怎么配置啊?
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
Go语言学习(十)| module 使用
go module 是在go 1.11版本才开始有的,需要将环境变量 GO111MODULE 设置为 on 才能正常使用
Mervyn
2020/07/21
3910
GO 依赖管理工具go Modules(官方推荐)
以前写过一篇关于go管理依赖包工具 dep的文章,当时认为dep将会成为官方依赖工具,现在看来是自己图样图斯内幕破了,正如官方一直提到dep是“official experiment”官方实验项目的那样,随着go modules 在go1.11版推出,go1.12版功能不断改进,再到go1.13版完善优化,正式扶正。预计dep将来也只能定格在“official experiment”了。
孤烟
2020/09/27
1.8K1
go modules:使用 mod 管理项目依赖包,通过vendor实现一键分发编译包
在go语言1.11版本之前,没有modules机制,所有软件包都在安装在$GOPATH/src目录下。不同项目如果引用了同一个软件包的不同版本,就会造成编译麻烦。修改$GOPATH变量是当时一种比较简单的解决方案。
LIYI
2020/03/25
6.6K0
Go——依赖管理
在Go1.5 release的版本的发布vendor目录被添加到除了GOPATH和GOROOT之外的依赖目录查找的解决方法。 查找依赖包路径的解决 当前包下的vendor目录 先上级的目录查找,直到找到scr的vendor目录 在GOPATH下面查找依赖包 在GOROOT目录下查找
羊羽shine
2019/05/29
1.4K0
Golang Module的使用 顶
注意:go mod 还有一些其他比较有意思的工具,比如可以打印依赖树,比如可以查看哪些模块在哪些包引用了
BGBiao
2019/09/09
1.3K0
用go-module作为包管理器搭建go的web服务器
本篇博客主要介绍了如何从零开始,使用Go Module作为依赖管理,基于Gin来一步一步搭建Go的Web服务器。并使用Endless来使服务器平滑重启,使用Swagger来自动生成Api文档。
SH的全栈笔记
2019/10/20
1.7K0
Go 编程 | 连载 21 - Go Modules 和 Package
GOPATH 是 Go 语言中使用的一个环境变量,它使用绝对路径提供项目的共工作目录,GOPATH 适合处理大量 Go 语言源码、多个包组合而成的复杂工程。
RiemannHypothesis
2022/09/28
5200
Golang中的包管理工具 - Go Modules
在Go1.5之前使用GOROOT和GOPATH这2个系统环境变量来决定包的位置,对于开发者主要使用GOPATH。GOPATH 解决了第三方源码依赖的问题,看一下我本机 $GOPATH/src 下的目录:
猿哥
2019/08/01
1.6K0
go module
go 1.5 引进了vendor管理工程依赖包,但是vendor的存放路径是在GOPATH底下,另外每个依赖还可以有自己的vendor,通常会弄得很乱,尽管dep管理工具可以将vendor平级化管理,但是相对GOPATH的路径是逃不掉的。另外,各个包的版本管理也显得原始,甚至有的开发将依赖包从github直接download下来自己放到GOPATH底下的vendor。go的依赖包管理一致是开发者诟病的一个痛点。所以在千呼万唤中,go 1.11 终于引进了go module管理工程的包依赖,去除了项目包管理对GOPATH的依赖,明确了依赖包的版本管理。
用户2937493
2019/09/10
1.3K0
go module
go mod与 govendor 区别与使用
这句话的意思是:把 go mod init 后下载的相关依 赖包(Gopath 的 pkg) 目录,拷贝到 vendor 目录。
王小明_HIT
2021/07/05
1.5K0
层次分明井然有条,Go lang1.18入门精炼教程,由白丁入鸿儒,Go lang包管理机制(package)EP10
    Go lang使用包(package)这种概念元素来统筹代码,所有代码功能上的可调用性都定义在包这个级别,如果我们需要调用依赖,那就“导包”就行了,无论是内部的还是外部的,使用import关键字即可。但事情往往没有那么简单,Go lang在包管理机制上走了不少弯路,虽然1.18版本的包管理已经趋于成熟,但前事不忘后事之师,我们还是需要了解一下这段历史。
用户9127725
2022/09/21
2520
浅谈Golang包管理module-aware
从Go 1.16 开始, module-aware 成为了默认模式,这表示 GO111MODULE 默认值为on. 换句话说就是,即使GO111MODULE不设置,也是使用 module-aware模式。 其实go mod从Go1.11就开始加入, Go1.13有重大变化,直到Go1.16成为默认,完全取代GOPATH模式。历史变化,见下表:
Markgogogo
2022/06/13
8040
浅谈Golang包管理module-aware
GoLang 新版包管理 -- go module 的使用
上一篇文章中,我们介绍了 GoLang 中包的使用与包管理机制。 GoLang 包的使用与管理
用户3147702
2022/06/27
2.4K0
GoLang 新版包管理 -- go module 的使用
Go语言基本环境变量与依赖管理
最近开始系统学习一下Golang这么新语言,记录一下它的基本环境变量配置以及依赖管理方式。编写本文的时候使用的Golang版本为go1.13.5 windows/amd64,其他版本不一定保证适合本文的内容。因为习惯,可能有时候把Go语言称为Go,有时候称为Golang。
Throwable
2020/06/23
9.3K1
Go Modules 详解
Go 1.11 和 Go 1.12 包含了初步的 Go Modules 支持,且计划在 2019 年 8 月发布的 Go 1.13 会在所有开发过程中默认使用 Go Modules。
码农编程进阶笔记
2021/07/20
8750
Go Modules 详解
[日常] gocron源码阅读-使用go mod管理依赖源码启动gocron
从 Go1.11 开始,golang 官方支持了新的依赖管理工具go mod go mod download: 下载依赖的 module 到本地 cache go mod edit: 编辑 go.mod go mod graph: 打印模块依赖图 go mod init: 在当前目录下初始化 go.mod(就是会新建一个 go.mod 文件) go mod tidy: 整理依赖关系,会添加丢失的 module,删除不需要的 module go mod vender: 将依赖复制到 vendor 下 go mod verify: 校验依赖 go mod why: 解释为什么需要依赖
唯一Chat
2019/11/14
8820
迁移到 Go Modules
Go 项目使用多种依赖管理策略,其中对 vendor 包的管理有两个比较流行的工具 dep 和 glide,但他们在行为上有很大的差异,而且并不是总能很好地同时使用。一些项目将其整个 GOPATH 目录存储在一个 Git 仓库中。其他人则只依赖于 go get 并期望在GOPATH中安装较新版本的依赖项。
恋喵大鲤鱼
2020/09/08
8520
Go Module详细使用教程,包管理不在难
go modules是 golang 1.11引入的新特性。模块是相关Go包的集合。modules是源代码交换和版本控制的单元。go命令直接支持使用modules,包括记录和解析对其他模块的依赖性。modules替换旧的基于GOPATH的方法来指定在给定构建中使用哪些源文件。
公号:咻咻ing
2020/03/04
20.6K0
跳出Go module的泥潭
Go 1.11 前天已经正式发布了,这个版本包含了两个最重要的feature就是 module和web assembly。虽然也有一些简单的教程介绍了go module的特性,但是基本上都是hello world的例子,在实践的过程中, 很多人都在“拼命的挣扎”,包括我自己, 从一些qq群、github的issue, twitter上都可以看到大家茫然或者抱怨的语句。
李海彬
2018/09/29
1.7K0
跳出Go module的泥潭
深入理解 Go Modules 的 go.mod 与 go.sum
流行的现代编程语言一般都提供依赖库管理工具,如 Java 的 Maven 、Python 的 PIP、Node.js 的 NPM 和 Rust 的 Cargo 等。Go 最为一门新生代语言,自然也有其自己的库管理方式。
恋喵大鲤鱼
2022/06/12
15K0
深入理解 Go Modules 的 go.mod 与 go.sum
相关推荐
Go语言学习(十)| module 使用
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档