Работаете на 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





