英文:
Content of go.sum and modules really used by a go application
问题
我正在尝试比较go mod tidy
的行为(以及go.sum的结果内容)与go list -m all
的输出。
阅读文档后,我了解到go.sum包含了在go.mod和依赖的go.mod文件中声明的所有依赖模块的完整列表,而go list -m all
则显示了在执行过程中实际加载的模块。
以一个包含logrus和prometheus的应用程序为例:
go.mod
module mytest
go 1.14
require (
github.com/prometheus/common v0.4.0
github.com/sirupsen/logrus v1.8.1
)
main.go
package main
import "github.com/sirupsen/logrus"
import "github.com/prometheus/common/version"
func main() {
logrus.Info("Hello World")
logrus.Infof("Prometheus info: %v", version.Info())
}
在执行go mod tidy
之后,go.sum中显示了logrus v1.8.1(由go.mod请求)和1.2.0(prometheus v0.4.0的依赖项);go list -m all
只显示了v1.8.1。
go.sum
[...]
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
[...]
go list
的输出
[...]
github.com/sirupsen/logrus v1.8.1
[...]
可以说通过go list -m all
列出的模块是应用程序实际使用的模块吗?
潜在的问题是,静态代码分析检测到go.sum中列出的不安全模块版本,但实际上这些版本在go list -m all
中并没有显示出来,因此它们不应该被应用程序真正使用,而只是在构建阶段下载以选择适当的最小版本。
一些参考资料:
https://go.dev/ref/mod#go-mod-tidy
> go mod tidy会假设所有构建标签都已启用,因此它将考虑特定于平台的源文件和需要自定义构建标签的文件,即使这些源文件通常不会被构建。
https://go.dev/ref/mod#go-sum-files
> go.sum文件可能包含多个版本的模块哈希值。为了执行最小版本选择,go命令可能需要从多个版本的依赖项中加载go.mod文件。go.sum也可能包含不再需要的模块版本的哈希值(例如,在升级后)。
> [...]此外,您的模块的go.sum记录了构建中使用的所有直接和间接依赖项的校验和(因此,您的go.sum中列出的模块通常比go.mod更多)。
https://github.com/golang/go/wiki/Modules#version-selection
> 最小版本选择算法用于选择构建中使用的所有模块的版本。对于构建中的每个模块,最小版本选择选择的版本始终是主模块或其依赖项中的require指令明确列出的语义最高版本。
>
> 例如,如果您的模块依赖于模块A
,该模块具有require D v1.0.0
,并且您的模块还依赖于模块B
,该模块具有require D v1.1.1
,那么最小版本选择将选择v1.1.1的D来包含在构建中(因为它是最高列出的require版本)。[...]要查看所选模块版本的列表(包括间接依赖项),请使用go list -m all
。
英文:
I'm trying to compare the behavior of go mod tidy
(and the resulting content of go.sum) to the output of go list -m all
.
Reading the docs, I understand go.sum contains the whole list of dependent modules declared in go.mod and in dependencies' go.mod files, go list -m all
shows the modules really loaded during the execution.
As an example, an application including logrus and prometheus like this:
go.mod
module mytest
go 1.14
require (
github.com/prometheus/common v0.4.0
github.com/sirupsen/logrus v1.8.1
)
main.go
package main
import "github.com/sirupsen/logrus"
import "github.com/prometheus/common/version"
func main() {
logrus.Info("Hello World")
logrus.Infof("Prometheus info: %v", version.Info())
}
After go mod tidy
, go.sum shows both logrus v1.8.1, requested by the go.mod, and 1.2.0, dependency of prometheus v0.4.0; go list -m all
shows only v1.8.1.
go.sum
[...]
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
[...]
output of go list
[...]
github.com/sirupsen/logrus v1.8.1
[...]
Is it correct to say the modules really used by the application are listed by go list -m all
?
The underlying problem is that a static code analysis detects insecure module versions listed in go.sum, but actually these versions don't show up in go list -m all
, hence they shouldn't be really used by the application, but only downloaded during build phase to select the proper minimal version.
Some reference:
https://go.dev/ref/mod#go-mod-tidy
> go mod tidy acts as if all build tags are enabled, so it will consider
> platform-specific source files and files that require custom build
> tags, even if those source files wouldn’t normally be built.
https://go.dev/ref/mod#go-sum-files
> The go.sum file may contain hashes for multiple versions of a module.
> The go command may need to load go.mod files from multiple versions of
> a dependency in order to perform minimal version selection. go.sum may
> also contain hashes for module versions that aren’t needed anymore
> (for example, after an upgrade).
> [...]In addition, your module's go.sum records checksums for all
> direct and indirect dependencies used in a build (and hence your
> go.sum will frequently have more modules listed than your go.mod).
https://github.com/golang/go/wiki/Modules#version-selection
> The minimal version selection algorithm is used to select the versions
> of all modules used in a build. For each module in a build, the
> version selected by minimal version selection is always the
> semantically highest of the versions explicitly listed by a require
> directive in the main module or one of its dependencies.
>
> As an example, if your module depends on module A
which has a
> require D v1.0.0
, and your module also depends on module B
which
> has a require D v1.1.1
, then minimal version selection would choose
> v1.1.1 of D to include in the build (given it is the highest listed
> require version). [...] To see a list of the selected module versions
> (including indirect dependencies), use go list -m all
.
答案1
得分: 8
是的,根据你提供的文档链接,使用go list -m all
列出了应用程序实际“使用”的模块。在这里,“使用”指的是在构建时为编译你的应用程序的Go代码选择的包。
我们在使用一个静态分析工具时遇到了类似的问题,我们不得不更改配置,使用go list -m all
的输出(转储到一个文件中),而不是使用go.sum
。
英文:
Yes, it correct to say the modules really "used" by the application are listed by go list -m all
(as per documentation you provided the link of). By "used", it means the package selected at build time for the compilation of the go code of your application.
We had a similar issue with a static analysis tool and we had to change the configuration to use the output of go list -m all
(dumped in a file) instead of go.sum
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论