Работаете на Go? Тогда вы наверняка сталкивались с этими загадочными GOPATH
, GOPRIVATE
, Go111module
и т. д. Хлопот они обычно не доставляют, но иногда возможны ошибки, из-за которых разработка резко замедляется.
Покажем, как этих ошибок избежать. Итак, начнем!
Внимание: применимо только к Go 1.15 и новее.
GOROOT
GOROOT — это место хранения SDK для Go, компиляторов по умолчанию, исполняемых команд и библиотек. Не изменяйте эту переменную, если не переходите на другую версию Go.
При импорте библиотеки поиск файла начинается с GOROOT
. Если файл не найден, поиск продолжается в GOPATH
.
GOPATH
В GOPATH
имеется три каталога: pkg
, src
и bin
.
$GOPATH/pkg
$GOPATH/pkg/mod
— это местоположение кеша модулей по умолчанию, где хранятся и кешируются загруженные черезgo get
илиgo install
зависимости.- Оно изменяется посредством редактирования переменной
GOMODCACHE
вgo env
.
$GOPATH/bin
- В каталоге
bin
хранятся установленные черезgo install
исполняемые команды, в том числе сторонние и из исходных файлов. - Стандартные команды, такие как
gofmt
, хранятся в каталогеGOROOT/bin
.
$GOPATH/src
- В каталоге
src
хранятся исходные файлы. - Но с появлением модулей он менее значим.
Модули Go
До модулей проекты и зависимости на Go хранились в каталоге $GOPATH/src/
.
Контроль версий отсутствовал. В проектах каталога src
библиотеки использовались в одной и той же стабильной версии, ветке master
.
Появились модули, и теперь:
- проекты можно создавать вне каталога
$GOPATH/src/
; - проект, он же модуль, — это набор выпускаемых вместе файлов и пакетов;
- в каждом модуле содержится файл
go.mod
, которым определяются требуемые зависимости и версии; - зависимости загружаются из соответствующих репозиториев во время сборки.
Go.mod
Файлом go.mod
определяются:
- путь к модулю, используемый при импорте пакетов/файлов в одном и том же модуле Go;
- зависимости и версии, необходимые для успешной сборки модуля.
Go.sum
При сборке на удаленном сервере в модуль из соответствующих систем контроля версий добавляются и загружаются указанные в файле go.mod
зависимости.
Здесь неизбежны проблемы:
- Что, если кто-то намеренно поменяет версию библиотеки?
- Как гарантировать, что на удаленном сервере добавляется библиотека с точным содержимым локальной копии?
Но с go.sum
они решаются:
- Это контрольная сумма всех прямых и косвенных зависимостей, перечисленных в
go.mod
. - Ею проверяется и гарантируется, что локальная загруженная копия зависимостей аналогична удаленной.
Go mod tidy
При запуске go mod tidy
:
- нужные зависимости загружаются, а ненужные из
go.mod
удаляются; - из локального кеша, то есть
$GOPATH/pkg/mod
, библиотеки не удаляются.
Go clean -modcache
Когда в Go выполняется go get
или go mod tidy
, зависимости загружаются и кешируются в GOMODCACHE
, то есть в $GOPATH/pkg/mod/
по умолчанию.
Этими кешированными библиотеками локальная разработка и локальная сборка сглаживаются.
Все загруженные пакеты удаляются из каталога GOMODCACHE
с помощью go clean -modcache
.
Go mod vendor
При сборке на удаленном сервере в модуль добавляются и загружаются указанные в файле go.mod
зависимости.
Но проблема с сетью или удаление одной из зависимостей в системе контроля версий чревато ошибками сборки.
Чтобы гарантировать воспроизводимую сборку, командой go mod vendor
в модуле создается папка и в каталоге сохраняются исходные файлы зависимостей.
Каталог vendor
сохраняется вместе с изменением кода.
Так обеспечивается:
- воспроизводимость и последовательность сборки;
- легкость просмотра изменений в зависимостях.
Однако каталог занимает дополнительное место и увеличивается время клонирования репозитория. В итоге CI/CD удлиняется.
GOPROXY
До появления GOPROXY
зависимости загружались из удаленных систем контроля версий напрямую.
Имелись две фундаментальные проблемы — безопасность и доступность. Зависимости в удаленной системе контроля версий можно было:
- в любое время удалить;
- изменить и скомпрометировать.
GOPROXY
— это централизованный репозиторий, в котором размещаются и кешируются общедоступные сторонние модули.
Теперь каждый запрос на загрузку перенаправляется на общедоступный GOPROXY
, а загруженный модуль проверяется на соответствие общедоступной базе данных контрольных сумм.
GOPROXY
настраивается в go env
. По умолчанию:
GOPROXY="https://proxy.golang.org"
Если нужный модуль в GOPROXY не найден, добавляем direct
:
GOPROXY="https://proxy.golang.org,direct"
и загружаем модуль из удаленной системы контроля версий.
GOPRIVATE
С общедоступными модулями хорошо справляется GOPROXY
. А что, если нужна зависимость из приватного репозитория, например репозитория компании?
Какие модули считать приватными, определяется командой GOPRIVATE
. Например:
GOPRIVATE=*github.com/org_name
В Go любой путь, соответствующий такому шаблону, приватный. Следовательно, прокси- и глобальная база данных контрольных сумм не используются.
Go111module
GO111module
означает режим с поддержкой модулей.
Диспетчера пакетов в Go не было до версии 1.11, когда появились модули. Зависимости получались через go get
и сохранялись с исходными файлами в $GOPATH/src
.
С появлением модулей загрузка, импорт и сохранение зависимостей изменились.
При GO111module=on
в Go активировано модульное поведение, при GO111module=off
— поведение GOPATH.
Поскольку модули Go теперь применяются на практике, поведение по умолчанию — GO111module=on
.
Заключение
У команд Go и переменных среды́ еще много нюансов.
Мы рассмотрели те, что встречаются в рабочем процессе разработки почти каждый день.
Читайте также:
- Go: трассировочный пакет
- Go: как циклы преобразуются в ассемблерную программу?
- Создание простого клиента RabbitMQ с помощью Go
Читайте нас в Telegram, VK и Дзен
Перевод статьи Jason Ngan: Go Commands and Env Vars Every Developer Should Know