Использование "go get" для загрузки бинарных файлов без добавления их в go.mod

Я использую модули Go в своем проекте и в своей системе сборки (например, Travis CI). Я загружаю утилиту командной строки (написанную на Go) с go get чтобы помочь с моим процессом сборки, например:

go get github.com/mitchellh/gox

Тем не менее, это go get вызывает добавление файла в мой go.mod файл. Это загрязняет среду сборки, делая ее "грязной" (так как в некоторых файлах, отслеживаемых в git, есть изменения, в данном случае go.mod и go.sum), и я использую git describe --always --dirty --tag описать мою сборку, которая выглядит как "грязная".

Есть ли способ "пойти получить" бинарный файл просто загрузить его, не добавляя его в go.mod/go.sum?

Я пытался установить GOPATH в другом месте, даже тогда, go get обновляет go.mod / go.sum, чтобы добавить это как // indirect зависимость.

dir="$(mktemp -d)"; \
  env GOPATH="$dir" go get github.com/mitchellh/gox && \
  mv "$dir/bin/gox" "$(go env GOPATH)"/bin/gox

3 ответа

Решение

Надеемся, что в Go 1.14 появится новый флаг для go get это именно то, что вы просите. Это отслеживается в выпуске № 30515 "cmd / go: предложить согласованную команду глобальной установки".

До этого у вас есть несколько разных вариантов.

Перейти 1.12 и 1.13: изменить каталог

Если вы используете Go 1.12 или более позднюю версию, простейшее решение, вероятно, состоит в том, чтобы переместиться за пределы вашего текущего модуля в каталог без go.mod до выполнения go get, такие как:

$ cd /tmp                              
$ go get github.com/foo/bar@v1.2.3
$ cd -                                # return to prior directory

Go 1.11, 1.12, 1.13+: гобин

gobin - это модульная команда для установки или запуска двоичных файлов, которая обеспечивает дополнительную гибкость, включая возможность установки без изменения текущего модуля. go.mod, Увидеть gobin README и FAQ для более подробной информации.

Go 1.11: временный модуль

Если вы используете Go 1.11 с модулями, первым шагом, вероятно, является обновление до Go 1.12 или 1.13, если в модулях есть много улучшений. Если вам необходимо использовать Go 1.11 и вы хотите использовать @version синтаксис без обновления вашего текущего модуля go.modТогда один из подходов заключается в создании временного модуля:

cd $(mktemp -d) && go mod init tempmod && go get github.com/foo/bar@v1.2.3

Это потому, что в Go 1.11 вы не можете использовать @version синтаксис, если вы не в модуле, который был ослаблен в Go 1.12. Этот подход был автоматизирован с помощью простого сценария оболочки @rogpeppe.

дополнительные детали

В общем, go Команда в модуле-модуле всегда определяет, в каком модуле он находится, в зависимости от текущего рабочего каталога, когда вы вызываете go команда. (Вы могли бы сделать аналогию с тем, как make без каких-либо аргументов будет искать make-файл в текущем рабочем каталоге, или как исторически go build без всяких аргументов создаст текущий рабочий каталог и т. д.).

С модулями, go get ищет go.mod файл в текущем рабочем каталоге или любом из его родителей, и go get будет использовать ограничения, перечисленные в любом go.mod как часть решения для версий, а также обновления go.mod если необходимо, основываясь на выполнении go get, Вот почему ваш go.mod файл обновляется, если вы запустите go get из существующего модуля.

С другой стороны, начиная с Go 1.12, если вы находитесь в каталоге, который не является частью какого-либо модуля (то есть каталог не имеет go.modМало кто из ее родителей), то нет go.mod обновить, но go Команда все еще может работать в режиме модуля и использовать @version синтаксис.

Из примечаний к выпуску Go 1.12:

Когда для GO111MODULE установлено значение on, команда go теперь поддерживает операции с поддержкой модулей вне каталога модуля, при условии, что этим операциям не нужно разрешать пути импорта относительно текущего каталога или явно редактировать файл go.mod. Такие команды, как go get, go list и go mod, ведут себя как в модуле с изначально пустыми требованиями. В этом режиме go env GOMOD сообщает о нулевом устройстве системы (/dev/null или NUL).

Go 1.16 и далее

Go 1.16 (выпущен в феврале 2021 г.) включает изменение, которое позволяет устанавливать двоичный файл, не затрагивая.

В выпуске 40276 отслеживается предложение:

cmd / go: 'go install' должен устанавливать исполняемые файлы в модульном режиме вне модуля

Это было реализовано в CL 254365 . В рамках этого изменения вы можете запустить, например:

      go install golang.org/x/tools/cmd/goimports@latest

установить двоичный файл, не затрагивая go.mod.

Чтобы установить определенную версию, замените @latest с например @v0.1.5.

В go help build:

Флаг сборки -mod обеспечивает дополнительный контроль над обновлением и использованием go.mod.

Если вызывается с -mod=readonly, команда go не допускается из неявного автоматического обновления go.mod

Другие вопросы по тегам