【问题标题】:go mod tidy error message: "but go 1.16 would select"go mod tidy 错误消息:“但是 go 1.16 会选择”
【发布时间】:2022-07-04 19:38:54
【问题描述】:

当我运行go mod tidy 时,一些包显示错误

> go mod tidy

github.com/myrepo/myproj imports
    go.k6.io/k6 imports
    go.k6.io/k6/cmd imports
    github.com/fatih/color loaded from github.com/fatih/color@v1.12.0,
    but go 1.16 would select v1.13.0

To upgrade to the versions selected by go 1.16:
    go mod tidy -go=1.16 && go mod tidy -go=1.17
If reproducibility with go 1.16 is not needed:
    go mod tidy -compat=1.17
For other options, see:
    https://golang.org/doc/modules/pruning

我已经安装了 go 1.17.9。错误是什么意思,为什么会触发?

【问题讨论】:

    标签: go go-modules


    【解决方案1】:

    此错误与 Go 1.17 中引入的 module graph pruning 有关。

    在 Go 1.16 中,用于最小版本选择的模块图过去包含完整的模块图,而在 1.17 中,该图仅包括传递依赖项(有一些例外,请参阅上面的链接)。

    现在要了解触发错误的原因,您可能需要查看Go 1.17 release notes

    默认情况下,go mod tidy 验证与主模块相关的依赖项的选定版本是否与之前的 Go 版本使用的版本相同(Go 1.16 用于指定 go 1.17 的模块)[...]

    因此,当您运行 go mod tidy 时,它会报告 Go 1.16“将选择”传递依赖项 (github.com/fatih/color) 的版本,该版本与 Go 1.17 的修剪图将选择的版本不同。

    这与构建可重现性有关,因为go.sum 包含go.mod 中指定的当前 Go 版本的校验和以及之前的版本。在 Go 1.17 和 Go 1.16 中模块图可以有效更改的情况下,go.sum 将不一致。

    错误消息建议进行两个修复。

    1. go mod tidy -go=1.16 && go mod tidy -go=1.17 — 这会选择依赖版本为 Go 1.16,然后选择为 Go 1.17

    2. go mod tidy -compat=1.17 — 这只是删除了 Go 1.16 校验和(因此提示“不需要 go 1.16 的可重复性”)。

    升级到 Go 1.18 后,该错误不会再出现,因为模块图的加载方式与 Go 1.17 相同。

    【讨论】:

      【解决方案2】:

      简单说明

      错误but go 1.16 would select 意味着现在您的编译软件(编译后的二进制文件)在使用 Go 1.16(或更低版本)而不是 Go 1.17(或更高版本)编译后的行为方式存在更深层次的问题。

      是什么导致了这个问题?:这可能完全超出您的控制范围,例如,您的一个依赖项的无害更改可能会将其作为副作用引入。 (正如最近看到的 golang.org/x/oauth2 和类似的,它已经破坏了世界各地的许多构建。)

      我可以简单地避免运行go mod tidy吗?可以,但这对您的实际问题没有任何帮助。

      那么对我有什么实际影响?到目前为止,您在 Go 1.16 和 1.17 之间没有构建可重复性。如果您使用 Go 1.16 构建或测试,您的程序的行为可能与 Go 1.17+ 的行为略有不同。程序的编译采用不同版本的依赖项。非常轻微的不同,但是不同。细节超出范围。

      全部迁移到 Go 1.17(或更高版本)

      1. 记录/传达任何人都不应该使用 Go 1.16 或更低版本编译您的代码。

      2. 确保您的持续集成未使用 Go 1.16 或更低版本。

      3. 在所有脚本、Makefile、管道等中,将命令 go mod tidy 更改为:

      go mod tidy -compat=1.17
      

      继续使用 Go 1.16(或更低版本)

      go mod tidy -go=1.16
      

      它声明你想在 1.16 冻结 go mod 行为。即使您使用 Go 1.17(或 1.18 等)构建,它也不会使用新的依赖修剪算法。您将获得一些 1.17+ 的新功能,但不是全部。

      (虽然go mod edit -go=1.16 有时在这里可能就足够了,但您通常需要tidy 以便使用新下载的版本/哈希更新go.sum。)

      额外症状

      在某些极端情况下,我看到ambiguous import 似乎只是针对非常相似的情况的不同措辞:

      example.com/foo/bar tested by
              example.com/foo/bar.test imports
              google.golang.org/grpc/credentials/oauth imports
              golang.org/x/oauth2/google imports
              cloud.google.com/go/compute/metadata: ambiguous import: found package cloud.google.com/go/compute/metadata in multiple modules:
              cloud.google.com/go v0.99.0 (/go/pkg/mod/cloud.google.com/go@v0.99.0/compute/metadata)
              cloud.google.com/go/compute v1.7.0 (/go/pkg/mod/cloud.google.com/go/compute@v1.7.0/metadata)
      

      此答案也适用于此类错误。

      等等,迁移什么?我从未真正使用过 Go 1.16?

      您可能认为在 go.mod 中声明版本 go 1.17 会强制使用该 Go 版本或更高版本。在这种情况下,即使是某些 Go 1.16 工具也会因go.mod file indicates go 1.17, but maximum supported version is 1.16 而失败,从而强制执行这种直觉。有道理,对吧?没有。

      残酷的现实是,只要您稍微调整一下构建过程,就可以使用 Go 1.16 或 Go 1.15编译这种类型的一些代码库(可能也是您的代码库)!核心团队不想默默地为这种人为的构建过程引入问题。这就是为什么面临明确保留或明确放弃这种向后兼容性的决定的原因。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-02-01
        • 2023-02-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多