С помощью «go list» как перечислить только модули Go, используемые в двоичном файле?

#go #go-modules #go-toolchain

#Вперед #go-модули #go-toolchain

Вопрос:

Я хочу перечислить модули (и их версии), которые скомпилированы в конечном исполняемом файле (а не в других зависимостях).

Я могу сделать это с:

 $ 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
  

Комментарии:

1. Что вы подразумеваете под «а не другими зависимостями»?

2. Но вы, вероятно, хотите Module , чтобы поле пакета было задокументировано .

3. Как подробно описано в отмеченном дубликате, шаблон {{if not .Indirect}}{{.}}{{end}} включает только прямые зависимости.

4. @icza .Indirect не исключает модули, которые используются в тестах. В моем примере github.com/google/go-cmp@v0.5.2 указан в go list , но не используется в двоичном файле.

5. @dolmen Это соответствует вашим потребностям? go list -deps -f '{{with .Module}}{{.Path}} {{.Version}}{{end}}'

Ответ №1:

Вот ответ:

 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/^tdept([^t]*)t([^t]*).*$/$1@$2/ amp;amp; 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