当***模块及其子模块之一作为单独版本单独导入时,如何解决冲突的 go 模块依赖关系?
Posted
技术标签:
【中文标题】当***模块及其子模块之一作为单独版本单独导入时,如何解决冲突的 go 模块依赖关系?【英文标题】:How to resolve conflicting go module dependencies when a top-level module and one of its sub-modules are separately imported as separate versions? 【发布时间】:2020-01-17 00:40:33 【问题描述】:我的项目中有两个依赖项。
go.mod
:
module github.com/test-org/test-repo
go 1.12
require (
github.com/foo/bar v1.0.0
github.com/raz/mataz v1.0.0
)
运行go mod download
后,这两个依赖项会导致下载github.com/shared/dependency
的两个不同版本。有趣的是github.com/shared/dependency
包含子模块,例如:
dependency
-- go.mod
-- api
-- go.mod
检查下载的模块显示两个版本已下载到我的本地计算机:
ls $GOPATH/pkg/mod/github.com/shared
:
[dir] dependency [dir] dependency@v1.1.0
ls $GOPATH/pkg/mod/github.com/shared/dependency
:
[dir] api@v1.2.0
查看这些目录的内容:
$GOPATH/pkg/mod/github.com/shared/dependency@v1.1.0
:
v1.1.0 中整个 repo 的文件内容,包括 api
文件夹及其自己的 go.mod
文件。
$GOPATH/pkg/mod/github.com/shared/dependency/api@v1.2.0
:
v1.2.0中repo的api
文件夹的文件内容,包括go.mod
文件。
最后,我的test-repo
中有一个.go
文件,设置如下:
package test-package
import (
"github.com/foo/bar"
)
func MyFunc() ...bar.NewBar()...
当我尝试运行MyFunc
(存在于其他地方)的测试时,我收到unknown import path...ambiguous import...
错误消息。例如
go test github.com/test-org/test-repo/test-package -test.run=TestMyFunc -v
:
unknown import path "github.com/shared/dependency/api": ambiguous import: found github.com/shared/dependency/api in multiple modules:
github.com/shared/dependency v1.1.0 ($GOPATH/pkg/mod/github.com/shared/dependency@v1.1.0/api)
github.com/shared/dependency v1.2.0 ($GOPATH/pkg/mod/github.com/shared/dependency/api@v1.2.0)
错误指向.go
文件的import
行,在github.com/foo/bar
存储库中导入github.com/shared/dependency/api
。鉴于有两个可用版本,它不知道在我的本地 $GOPATH/pkg/mod
文件夹中选择哪个 api
:
$GOPATH/pkg/mod/github.com/shared/dependency@v1.1.0/api
$GOPATH/pkg/mod/github.com/shared/dependency/api@v1.2.0
有什么方法可以使go test
调用工作(解决依赖冲突)?我的两个依赖项都没有明确要求下载完整的shared/dependency@v1.1.0
,但由于某种原因它被拉入。如果不存在,它似乎可以解决问题。
【问题讨论】:
主版本 > 1 的包必须以“/v2”结尾的导入路径导入。您不能在两个不同版本中拥有相同的包(由其导入路径标识)。这就是为什么不同的版本需要不同的导入路径:Append v2.查阅解释所有这些的 Go Modules wiki。 (可能重复)。 Go 模块概念建立在模块必须根据 semver 进行语义版本控制。如果你的一个要求是v1.12
,另一个是v1.0
,那是相同的主要版本,因此v1.12
必须与v1.0
兼容,所以go工具会选择v1.12
应该可以工作.如果您需要不同的主要版本,以v2
开头的它必须是导入路径的一部分,因此它将被视为不同的包/依赖项,并且所有不同的主要版本都将单独包含。
@Volker,我已经更改了问题中的版本,因为我的问题实际上不是v1
与v2
,而是v0
与v1
。所以你的建议不适用。不过,我不知道您提到的v2
+ 细节。很高兴知道。
您不能拥有同一个包的 v0.0.0 和 v1.0.0。死的简单。 v0.0.0 甚至无效,仅用于兼容性。有时你所能做的就是修复上游。
@Volker 好的,所以如果我的一个依赖项需要 v0.x.x
版本的包,而另一个依赖项需要 v1.x.x
版本,唯一的解决方案是更改以下要求之一这些依赖项在其go.mod
文件中吗?那是对的吗?最初使用 go modules 时,我的印象是子模块可能能够摆脱不同的版本。例如,如果我在我的 repo 中为需要其他版本的依赖项的包创建了第二个 go.mod
文件,我认为这可能有效,但我可能会偏离 go 模块的能力。跨度>
【参考方案1】:
问题是其中一个依赖项引用了 pre-go-modules 的 github.com/shared/dependency/api
版本。
这导致 go 工具有一个对 github.com/shared/dependency/api
子模块的模块引用,而且还对 pre-go-modules 版本的整个 github.com/shared/dependency
存储库进行了黑盒导入。在这个例子中,这意味着v1.2.0
有 go 模块(有一个go.mod
文件),而v1.1.0
没有。
将以下行添加到我的 go.mod
文件中能够解决该问题,并且此解决方案适用于我遇到此类冲突的多个依赖项:
replace (
github.com/shared/dependency => github.com/shared/dependency v1.2.0
)
请注意,此解决方案之所以有效,是因为我们强制对共享依赖项的引用使用支持 go-module 的版本(v1.2.0+)。
【讨论】:
以上是关于当***模块及其子模块之一作为单独版本单独导入时,如何解决冲突的 go 模块依赖关系?的主要内容,如果未能解决你的问题,请参考以下文章