为什么从 Go 1.17 开始 go.mod 中有两个“require”块?

joz*_*ozo 39 go go-modules

我创建了一个小型 go 应用程序。几天前,我从 go 1.15 升级到 1.17,并且还使用go get -u. 更改后,我的 go.mod 文件中有 2 个 require 块。为什么?这是什么意思?没问题还是有什么东西坏了?

应用程序仍然可以正确构建。

go.mod 文件:

module github.com/jozo/simple-pomodoro

go 1.17

require (
    fyne.io/fyne/v2 v2.1.0
    github.com/dsnet/golib/memfile v1.0.0
    github.com/faiface/beep v1.1.0
    github.com/fsnotify/fsnotify v1.5.1 // indirect
    github.com/go-gl/gl v0.0.0-20210905235341-f7a045908259 // indirect
    github.com/go-gl/glfw/v3.3/glfw v0.0.0-20210727001814-0db043d8d5be // indirect
    github.com/godbus/dbus/v5 v5.0.5 // indirect
    github.com/hajimehoshi/oto v1.0.1 // indirect
    github.com/srwiley/oksvg v0.0.0-20210519022825-9fc0c575d5fe // indirect
    github.com/srwiley/rasterx v0.0.0-20210519020934-456a8d69b780 // indirect
    github.com/yuin/goldmark v1.4.1 // indirect
    golang.org/x/exp v0.0.0-20210916165020-5cb4fee858ee // indirect
    golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d // indirect
    golang.org/x/mobile v0.0.0-20210924032853-1c027f395ef7 // indirect
    golang.org/x/net v0.0.0-20210929193557-e81a3d93ecf6 // indirect
    golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 // indirect
    golang.org/x/text v0.3.7 // indirect
    gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
)

require (
    github.com/davecgh/go-spew v1.1.1 // indirect
    github.com/fredbi/uri v0.0.0-20181227131451-3dcfdacbaaf3 // indirect
    github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff // indirect
    github.com/pkg/errors v0.9.1 // indirect
    github.com/pmezard/go-difflib v1.0.0 // indirect
    github.com/stretchr/testify v1.7.0 // indirect
)
Run Code Online (Sandbox Code Playgroud)

bla*_*een 49

因为在 Go 1.17 中,模块图已更改为启用修剪和延迟加载。第二个require块包含间接依赖项。

https://golang.org/doc/go1.17#go-command

如果模块指定 go 1.17 或更高版本,则模块图仅包含其他 go 1.17 模块的直接依赖项,而不包含它们的完整传递依赖项。[...]

[...] 如果模块在其 go.mod 文件中指定 go 1.17 或更高版本,则其 go.mod 文件现在为每个提供传递导入包的模块包含显式 require 指令。(在以前的版本中,go.mod 文件通常只包含直接导入包的明确要求。)

由于扩展后的 Go 1.17 go.mod 文件中显式需求的数量可能会大得多,因此 go 1.17 模块中新添加的间接依赖项需求将维护在与包含直接依赖项的块不同的独立 require 块中。

注意:go.mod您在问题中发布的文件//indirect在第一个 require 块中有依赖项。我怀疑,根据引用文档中的“新添加”措辞,这是因为这些//indirect依赖项已经在那里列出,并且go mod tidy没有重新排列它们。如果你:

  • 手动删除其中之一
  • 和/或重新创建go.mod文件,并将 Go 版本设置为1.17或更高版本
  • 和/或运行go mod tidy -go=1.17

然后它将分离//indirect两个块中的直接和依赖关系。不管怎样,这是一种视觉上的便利,文档并不强制要求创建两个单独的块。


附加参考:

  • 为了澄清,这两种格式都是完全有效的,第二个块只是用于在视觉上分离新添加的依赖项,并在应用更改时进行更简单的差异。 (5认同)