使用"go list"命令如何列出仅在二进制文件中使用的Go模块?

5
我可以帮您列出最终可执行文件中编译的模块(及其版本),而不包括其他依赖项。以下是代码示例:
$ go build -o a.out
$ go version -m a.out

但是我该如何使用 go list(它具有方便的JSON输出)来实现呢?

我尝试了这个方法:

$ go list -m -f '{{define "M"}}{{.Path}}@{{.Version}}{{end}}{{if not .Main}}{{if .Replace}}{{template "M" .Replace}}{{else}}{{template "M" .}}{{end}}{{end}}' all

但是它列出了许多传递依赖项,这些依赖项仅在测试套件中使用。

我不知道如何过滤掉这些依赖项。

以下是一个示例项目以查看问题(可在Go Playground上获取):

main.go

package main

import "fmt"

func main() {
    fmt.Println("Hello, world!")
}

main_test.go:

package main

import (
    "github.com/google/go-cmp/cmp"
    "testing"
)

func TestHelloWorld(t *testing.T) {
    if !cmp.Equal(1, 1) {
        t.Fatal("FAIL")
    }
}

go.mod:

module play.ground

go 1.15

require github.com/google/go-cmp v0.5.2

$ go build -o hello ; go version -m hello
hello: go1.15
    path    play.ground
    mod play.ground (devel)
$ go list -m -f '{{define "M"}}{{.Path}}@{{.Version}}{{end}}{{if not .Main}}{{if .Replace}}{{template "M" .Replace}}{{else}}{{template "M" .}}{{end}}{{end}}' all
github.com/google/go-cmp@v0.5.2
golang.org/x/xerrors@v0.0.0-20191204190536-9bdfabe68543

“and not other dependencies” 是什么意思? - Jonathan Hall
但是您可能想要包的Module字段,如文档所述。 - Jonathan Hall
正如标记为重复的内容所述,模板 {{if not .Indirect}}{{.}}{{end}} 仅包括直接依赖项。 - icza
@icza。Indirect 不会排除在测试中使用的模块。在我的例子中,github.com/google/go-cmp@v0.5.2go list 中被列出,但并未在二进制文件中使用。 - dolmen
@dolmen 这个是否符合您的需求?go list -deps -f '{{with .Module}}{{.Path}} {{.Version}}{{end}}' - icza
@icza 不行,它仍然列出了太多的模块。但这帮助我找到了解决问题的方法。但我不能将其作为答案发布在这里,因为我的问题被错误地标记为重复。 - dolmen
1个回答

10

这里是答案:


go list -deps -f '{{define "M"}}{{.Path}}@{{.Version}}{{end}}{{with .Module}}{{if not .Main}}{{if .Replace}}{{template "M" .Replace}}{{else}}{{template "M" .}}{{end}}{{end}}{{end}}' | sort -u

注意:go list -deps 会为每个包生成一行。因此,从多个包中导入的模块将被列出多次。sort -u 对其进行排序并删除重复项。
它可以与以下内容进行比较:
go version -m hello | perl -ne 's/^\tdep\t([^\t]*)\t([^\t]*).*$/$1\@$2/ && print' | sort

这里是一个更详细的版本,列出了每个模块引用的每个包(还使用了 jq):
go list -deps -f '{{define "mod"}}{{.Path}}@{{.Version}}{{end}}{{if .Module}}{{if not .Module.Main}}{{if .Module.Replace}}{{template "mod" .Module.Replace}}{{else}}{{template "mod" .Module}}{{end}}{{"\t"}}{{.ImportPath}}{{end}}{{end}}' | sort
go list -deps -json | jq -r 'select(.Module and (.Module.Main | not)) | .Module.Path + "@" + .Module.Version + "\t" + .ImportPath' | sort

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接