使用“转到列表”如何仅列出二进制文件中使用的转到模块?

问题描述

我想列出在最终可执行文件(而不是其他依赖项)中编译的模块(及其版本)。

我可以这样:

$ 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

但是它列出了许多传递依赖,例如仅在测试套件中使用。 我看不到如何过滤掉那些依赖项。

这是一个示例项目,可以看到问题(on The 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

解决方法

这是答案:

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