当***模块及其子模块之一作为单独版本单独导入时,如何解决冲突的 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,我已经更改了问题中的版本,因为我的问题实际上不是v1v2,而是v0v1。所以你的建议不适用。不过,我不知道您提到的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-modulesgithub.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 模块依赖关系?的主要内容,如果未能解决你的问题,请参考以下文章

Python中模块使用及面向对象介绍

模块使用

模块使用面向对象介绍

15模块

Python-模块的使用

是否可以使用webpack单独导入捆绑的webpack和库?