问题

最近遇到了一个很奇怪的问题,如下:

diskimage/image imports
        fastdev/disk imports
        github.com/gin-gonic/gin imports
        github.com/gin-gonic/gin/binding imports
        github.com/ugorji/go/codec: ambiguous import: found package github.com/ugorji/go/codec in multiple modules:
        github.com/ugorji/go v1.1.4 (F:\GOPATH\pkg\mod\github.com\ugorji\go@v1.1.4\codec)
        github.com/ugorji/go/codec v0.0.0-20190204201341-e444a5086c43 (F:\GOPATH\pkg\mod\github.com\ugorji\go\codec@v0.0.0-20190204201341-e444a5086c43)

fastdev(自己的内部仓库)引用了 github.com/ugorji/go v1.1.4 这个仓库。而 gin 引用了 github.com/ugorji/go/codec v0.0.0-20190204201341-e444a5086c43 仓库,然后 module 不知道去找哪个包了??我并没有做过什么骚操作呀,为什么会出现这种问题?

解决思路

带着疑惑打开了作者的 github 的主页,找到了相应的库,发现 github.com/ugorji/go 这个库就有个 codec 的目录。
仓库

按理说,只要 mod 中引入 github.com/ugorji/go 即可,但是又怎么会单独又能引用 github.com/ugorji/go/codec 呢, 点击进入 codec 目录,才发现了猫腻,原来这里也有个 go.mod 文件。
codec
之前从来没见过这种用法,一般都是直接在整个仓库的最外层有一个 go.mod,内部不会再出现的。

由于 codec 目录下也有个 go.mod,所以我们可以直接引用 github.com/ugorji/go/codec

问题为何出现渐渐有了思路,应该是go把 github.com/ugorji/go/codecgithub.com/ugorji/go 这两个path当成不同的模块引入导致的冲突

在作者的 github 仓库的 README.md 中,发现了作者对于该仓库的 mod 用法的解释。
作者答
简单说来,就是该库的作者自己错误的使用了 go mod 的特性导致的代码仓库引用的问题。
现在再回头看看引用有问题的 v1.1.4 这个 tag,当时 codec 目录下并没有 go.mod 文件,顾 使用 go module 引用 github.com/ugorji/go/codec 时,go 会根据 path 找到 github.com/ugorji/go 这个仓库并将其作为一个包引入,github.com/ugorji/go 下有 codec 的文件。 但是我们的 gin 引用的 v0.0.0-20190204201341-e444a5086c43 (对应的是 v1.1.2) 这时 codec 目录下已经有了 go.mod 文件,引入 github.com/ugorji/go/codec 时,又会重新引入一个版本的 codec。这时的目录结构如下:

GOPATH\pkg\mod\github.com\ugorji
 - go
 	- codec@v0.0.0-20190204201341-e444a5086c43
 		- xxx
 - go@v1.1.4
	- codec
		- xxx
	- xxx



所以,当我们同时引用了这两个版本的仓库时,就会导致 module 的冲突。

解决方式

直接将 github.com/ugorji/go v1.1.4 的引用升级到 v1.2.6 ,将 github.com/ugorji/gogithub.com/ugorji/go/codec 当做两个包来引用即可。

总结

出现该问题,主要是作者没有搞清楚 go module 的使用,代码仓库从最初的 gopath 转向 go mod 中遇到的坑,可见作者在 mod 这里也纠结了很久。
其实在不清楚特性之前,看看官方文档比较好,作者遇到的问题,在 go 官方的 wiki 中都有描述。

题外话

github.com/ugorji/go 这个仓库中

    github.com/ugorji/go (requires github.com/ugorji/go/codec)
    github.com/ugorji/go/codec (requires github.com/ugorji/go) 
    github.com/ugorji/go/codec/codecgen (requires github.com/ugorji/go/codec)
    github.com/ugorji/go/codec/bench (requires github.com/ugorji/go/codec) 

这样不是会循环引用吗?为什么没有报错呢?

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐