пятница, 26 марта 2021 г.

Новые изменения модулей в Go 1.16

В Go 1.16 много новых функций, особенно для модулей. В примечаниях к релизу кратко описаны эти изменения, но давайте подробно рассмотрим некоторые из них.

Модули включены по умолчанию

Команда go теперь по умолчанию создает пакеты в режиме с поддержкой модулей, даже если go.mod отсутствует. Это большой шаг к использованию модулей во всех проектах.

По-прежнему можно создавать пакеты в режиме GOPATH, отключив переменную среды GO111MODULE. Вы также можете установить GO111MODULE на auto, чтобы включить режим с поддержкой модулей, только если файл go.mod присутствует в текущем или любом родительском каталоге. Раньше это было по умолчанию. Обратите внимание, что вы можете установить GO111MODULE и другие переменные навсегда с помощью go env -w:

go env -w GO111MODULE=auto

Планируется отказ от поддержки режима GOPATH в Go 1.17. Другими словами, Go 1.17 игнорирует GO111MODULE. Если у вас есть проекты, которые не собираются в режиме с поддержкой модулей, сейчас самое время выполнить миграцию. Если есть проблема, мешающая вам выполнить миграцию, рассмотрите возможность заполнения проблемы или отчета об опыте.

Никаких автоматических изменений go.mod и go.sum

Раньше, когда команда go обнаруживала проблему с go.mod или go.sum, например, отсутствующую директиву require или отсутствующую сумму, она пыталась устранить проблему автоматически. Было получено много отзывов о том, что такое поведение было неожиданным, особенно для таких команд, как go list, которые обычно не имеют побочных эффектов. Автоматические исправления не всегда были желательными: если импортированный пакет не был предоставлен каким-либо обязательным модулем, команда go добавляла новую зависимость, возможно, вызывая обновления общих зависимостей. Даже неверный путь импорта приведет к (неудачному) поиску в сети.

В Go 1.16 команды с поддержкой модулей сообщают об ошибке после обнаружения проблемы в go.mod или go.sum, вместо того, чтобы пытаться исправить проблему автоматически. В большинстве случаев сообщение об ошибке рекомендует команду для устранения проблемы.

$ go build
example.go:3:8: no required module provides package golang.org/x/net/html; to add it:
    go get golang.org/x/net/html
$ go get golang.org/x/net/html
$ go build

Как и раньше, команда go может использовать каталог vendor, если он присутствует. Такие команды, как go get and go mod tidy, по-прежнему изменяют go.mod и go.sum, поскольку их основная цель - управлять зависимостями.

Установка исполняемого файла определенной версии

Команда go install теперь может установить исполняемый файл определенной версии, указав суффикс @version.

go install golang.org/x/tools/gopls@v0.6.5

При использовании этого синтаксиса go install устанавливает команду из этой точной версии модуля, игнорируя любые файлы go.mod в текущем каталоге и родительских каталогах. (Без суффикса @version go install продолжает работать как всегда, собирая программу с использованием требований к версии и замен, перечисленных в go.mod текущего модуля.)

Раньше рекомендовалось go get -u program для установки исполняемого файла, но это использование вызвало слишком сильную путаницу со значением go get для добавления или изменения требований к версии модуля в go.mod. И чтобы избежать случайного изменения go.mod, люди начали предлагать более сложные команды, такие как:

cd $HOME; GO111MODULE=on go get program@latest

Теперь мы все можем использовать go install program@latest.

Чтобы устранить двусмысленность в отношении используемых версий, существует несколько ограничений на то, какие директивы могут присутствовать в файле go.mod программы при использовании этого синтаксиса установки. В частности, директивы replace и exclude запрещены, по крайней мере, на данный момент. В долгосрочной перспективе, когда новая программа go install program@version будет работать хорошо для достаточного количества вариантов использования, планируется сделать так, чтобы go get прекратил установку двоичных файлов команд.

Отзыв модуля

Вы когда-нибудь случайно публиковали версию модуля до того, как она была готова? Или вы обнаружили проблему сразу после публикации версии, которую нужно было быстро исправить? Ошибки в опубликованных версиях трудно исправить. Чтобы сборки модулей оставались детерминированными, версия не может быть изменена после публикации. Даже если вы удалите или измените тег версии, proxy.golang.org и другие прокси-серверы, вероятно, уже имеют исходный кешированный файл.

Авторы модулей теперь могут отзывать версии модулей с помощью директивы retract в go.mod. Отозванная версия все еще существует и может быть загружена (поэтому сборки, которые от нее зависят, не сломаются), но команда go не выберет ее автоматически при разрешении версий, таких как @latest. go get and go list -m -u выведет предупреждения о существующем использовании.

Например, предположим, что автор популярной библиотеки example.com/lib выпускает v1.0.5, а затем обнаруживает новую проблему безопасности. Он может добавить в свой файл go.mod директиву, подобную приведенной ниже:

// Remote-triggered crash in package foo. See CVE-2021-01234.
retract v1.0.5

Затем автор может пометить и опубликовать версию v1.0.6, новую высшую версию. После этого пользователи, которые уже зависят от версии 1.0.5, будут уведомлены об отзыве при проверке наличия обновлений или при обновлении зависимого пакета. Сообщение с уведомлением может включать текст из комментария над директивой retract.

$ go list -m -u all
example.com/lib v1.0.5 (retracted)
$ go get .
go: warning: example.com/lib@v1.0.5: retracted by module author:
    Remote-triggered crash in package foo. See CVE-2021-01234.
go: to switch to the latest unretracted version, run:
    go get example.com/lib@latest

Управление инструментами контроля версий с помощью GOVCS

Команда go может загружать исходный код модуля с зеркала, такого как proxy.golang.org, или напрямую из репозитория системы управления версиями, используя git, hg, svn, bzr или fossil. Прямой доступ к управлению версиями важен, особенно для частных модулей, которые недоступны на прокси-серверах, но это также потенциально проблема безопасности: ошибка в инструменте управления версиями может быть использована вредоносным сервером для запуска непредусмотренного кода.

Go 1.16 представляет новую конфигурационную переменную GOVCS, которая позволяет пользователю указывать, каким модулям разрешено использовать определенные инструменты контроля версий. GOVCS принимает разделенный запятыми список правил pattern:vcslist. pattern - это path.Match шаблон соответствующий одному или нескольким ведущим элементам пути к модулю. Специальные шаблоны public и private соответствуют общедоступным и частным модулям (private определяется как модули, соответствующие шаблонам в GOPRIVATE; public - это все остальное). Vcslist - это список разрешенных команд управления версиями, разделенных вертикальной чертой, или ключевое слово all или off.

Например:

GOVCS=github.com:git,evil.com:off,*:git|hg

С этой настройкой модули с путями на github.com можно загружать с помощью git; пути на evil.com нельзя загрузить с помощью какой-либо команды управления версиями, а все другие пути (* соответствует всему) можно загрузить с помощью git или hg.

Если GOVCS не установлен или модуль не соответствует какому-либо шаблону, команда go использует значение по умолчанию: git и hg разрешены для общедоступных модулей, а все инструменты разрешены для частных модулей. Причина, по которой разрешено использование только Git и Mercurial, заключается в том, что эти две системы уделяли наибольшее внимание вопросам работы в качестве клиентов ненадежных серверов. Напротив, Bazaar, Fossil и Subversion в основном использовались в надежных, аутентифицированных средах и не так тщательно изучаются, как поверхности для атак. То есть настройка по умолчанию:

GOVCS=public:git|hg,private:all


Читайте также:


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

Отправить комментарий