Спецификация по модулям языка программирования Go
Categories:
Введение
Модули — это способ, с помощью которого Go управляет зависимостями.
Этот документ является подробным справочным руководством по модульной системе Go. Введение в создание проектов Go см. в статье «Как писать код на Go». Информацию об использовании модулей, переносе проектов на модули и других темах см. в серии статей в блоге, начиная с «Использование модулей Go».
Модули, пакеты и версии
Модуль — это набор пакетов, которые выпускаются, версионируются и распространяются вместе. Модули можно загружать напрямую из репозиториев контроля версий или с прокси-серверов модулей.
Модуль идентифицируется по пути модуля, который объявляется в файле go.mod вместе с информацией о зависимостях модуля. Корневой каталог модуля — это каталог, содержащий файл go.mod
. Главный модуль — это модуль, содержащий каталог, в котором вызывается команда go
.
Каждый пакет в модуле представляет собой набор исходных файлов в одном каталоге, которые компилируются вместе. Путь к пакету — это путь к модулю, соединенный с подкаталогом, содержащим пакет (относительно корня модуля). Например, модуль «golang.org/x/net»
содержит пакет в каталоге «html». Путь к этому пакету — «golang.org/x/net/html»
.
Пути к модулям
Путь модуля — это каноническое имя модуля, объявленное с помощью директивы module в файле go.mod
модуля. Путь модуля является префиксом для путей пакетов внутри модуля.
Путь модуля должен описывать как то, что делает модуль, так и то, где его найти. Обычно путь модуля состоит из пути корня репозитория, каталога внутри репозитория (обычно пустого) и суффикса основной версии (только для основной версии 2 или выше).
-
Путь корня репозитория — это часть пути модуля, которая соответствует корневому каталогу репозитория контроля версий, в котором разрабатывается модуль. Большинство модулей определены в корневом каталоге своего репозитория, поэтому обычно это весь путь. Например,
golang.org/x/net
— это путь корня репозитория для модуля с таким же именем. См. раздел Поиск репозитория для пути модуля, чтобы узнать, как команда go находит репозиторий с помощью HTTP-запросов, полученных из пути модуля. -
Если модуль не определен в корневом каталоге репозитория, подкаталог модуля является частью пути модуля, которая называет каталог, не включая суффикс основной версии. Это также служит префиксом для семантических тегов версии. Например, модуль
golang.org/x/tools/gopls
находится в подкаталогеgopls
репозитория с корневым путемgolang.org/x/tools
, поэтому он имеет подкаталог модуляgopls
. См. раздел «Сопоставление версий с коммитами» и «Каталоги модулей в репозитории». -
Если модуль выпускается с основной версией 2 или выше, путь модуля должен заканчиваться суффиксом основной версии, например
/v2
. Это может быть частью имени подкаталога или нет. Например, модуль с путемgolang.org/x/repo/sub/v2
может находиться в подкаталоге/sub
или/sub/v2
репозиторияgolang.org/x/repo
.
Если модуль может зависеть от других модулей, необходимо соблюдать эти правила, чтобы команда go
могла найти и загрузить модуль. Существует также несколько лексических ограничений на символы, разрешенные в путях модулей.
Модуль, который никогда не будет загружен в качестве зависимости другого модуля, может использовать любой допустимый путь пакета в качестве пути модуля, но необходимо следить за тем, чтобы он не конфликтовал с путями, которые могут использоваться зависимостями модуля или стандартной библиотекой Go. Стандартная библиотека Go использует пути к пакетам, которые не содержат точку в первом элементе пути, и команда go не пытается разрешить такие пути с сетевых серверов. Пути example и test зарезервированы для пользователей: они не будут использоваться в стандартной библиотеке и подходят для использования в автономных модулях, таких как те, которые определены в учебных пособиях или примерах кода, или созданы и обрабатываются как часть теста.
Версии
Версия идентифицирует неизменяемый снимок модуля, который может быть либо релизом, либо предварительной версией. Каждая версия начинается с буквы v
, за которой следует семантическая версия. Подробнее о том, как версии форматируются, интерпретируются и сравниваются, см. Semantic Versioning 2.0.0
.
Вкратце, семантическая версия состоит из трех неотрицательных целых чисел (версии major
, minor
и patch
, слева направо), разделенных точками. За версией patch может следовать необязательная строка предварительной версии, начинающаяся с дефиса. За строкой предварительной версии или версией patch может следовать строка метаданных сборки, начинающаяся с плюса. Например, v0.0.0
, v1.12.134
, v8.0.5-pre
и v2.0.9+meta
являются действительными версиями.
Каждая часть версии указывает, является ли версия стабильной и совместимой с предыдущими версиями.
- Основная версия должна быть увеличена, а второстепенная и патч-версия должны быть установлены в ноль после внесения обратно несовместимых изменений в публичный интерфейс модуля или задокументированную функциональность, например, после удаления пакета.
- Второстепенная версия должна быть увеличена, а патч-версия установлена в ноль после внесения обратно совместимых изменений, например, после добавления новой функции. Версия патча должна быть увеличена после изменения, которое не влияет на публичный интерфейс модуля, например исправления ошибки или оптимизации.
- Суффикс предварительной версии указывает, что версия является предварительной. Предварительные версии сортируются перед соответствующими выпусками. Например,
v1.2.3-pre
идет передv1.2.3
. - Суффикс метаданных сборки игнорируется при сравнении версий. Команда
go
принимает версии с метаданными сборки и преобразует их в псевдоверсии, чтобы сохранить полный порядок между версиями.- Специальный суффикс
+incompatible
обозначает версию, выпущенную до перехода на модули версии2
или более поздней (см. Совместимость с репозиториями, не являющимися модулями). - Специальный суффикс
+dirty
добавляется к информации о версии бинарного файла, когда он скомпилирован с помощью инструментария Go 1.24 или более поздней версии в рамках действительного локального репозитория системы контроля версий(VCS)
, который содержит нефиксированные изменения в рабочем каталоге.
- Специальный суффикс
Версия считается нестабильной, если ее основная версия равна 0
или она имеет суффикс предварительной версии. Нестабильные версии не подпадают под требования совместимости. Например, v0.2.0
может быть несовместима с v0.1.0
, а v1.5.0-beta
может быть несовместима с v1.5.0
.
Go может получать доступ к модулям в системах контроля версий, используя теги, ветки или ревизии, которые не соответствуют этим соглашениям.
Однако в основном модуле команда go
автоматически преобразует имена ревизий, которые не соответствуют этому стандарту, в канонические версии.
Команда go
также удаляет суффиксы метаданных сборки (за исключением +incompatible
) в рамках этого процесса. Это может привести к появлению псевдоверсии, предварительной версии, которая кодирует идентификатор ревизии (например, хэш Git commit
) и временную метку из системы контроля версий.
Например, команда
go get golang.org/x/net@daa7c041
преобразует хеш коммитаdaa7c041
в псевдоверсиюv0.0.0-20191109021931-daa7c04131f5
. Канонические версии требуются за пределами основного модуля, и командаgo
сообщит об ошибке, если в файлеgo.mod
появится неканоническая версия, такая какmaster
.
Псевдоверсии
Псевдоверсия — это специально отформатированная предварительная версия, которая кодирует информацию об определенной ревизии в репозитории системы контроля версий. Например, v0.0.0-20191109021931-daa7c04131f5
— это псевдоверсия.
Псевдоверсии могут относиться к ревизиям, для которых нет семантических тегов версий. Они могут использоваться для тестирования коммитов перед созданием тегов версий, например, в ветке разработки.
Каждая псевдоверсия состоит из трех частей:
- Префикс базовой версии (
vX.0.0
илиvX.Y.Z-0
), который либо получен из семантического тега версии, предшествующего ревизии, либоvX.0.0
, если такого тега нет. - Временная метка (ггггммддччммсс), которая представляет собой время UTC, когда была создана ревизия. В Git это время коммита, а не время автора.
- Идентификатор ревизии (abcdefabcdef), который представляет собой 12-символьный префикс хеша коммита или, в Subversion, номер ревизии с нулевым заполнением.
Каждая псевдоверсия может иметь одну из трех форм, в зависимости от базовой версии. Эти формы гарантируют, что псевдоверсия будет выше базовой версии, но ниже следующей версии с тегом.
vX.0.0-yyyymmddhhmmss-abcdefabcdef
используется, когда базовая версия неизвестна. Как и во всех версиях, основная версияX
должна совпадать с суффиксом основной версии модуля.vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef
используется, когда базовая версия является предварительной версией, такой какvX.Y.Z-pre
.vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdefabcdef
используется, когда базовая версия является релизной версией, такой какvX.Y.Z
. Например, если базовая версия —v1.2.3
, псевдоверсия может бытьv1.2.4-0.20191109021931-daa7c04131f5
.
Несколько псевдоверсий могут ссылаться на одну и ту же фиксацию, используя разные базовые версии. Это происходит естественным образом, когда после записи псевдоверсии помечается более низкая версия.
Эти формы придают псевдоверсиям два полезных свойства:
- Псевдоверсии с известными базовыми версиями сортируются выше этих версий, но ниже других предварительных версий для более поздних версий.
- Псевдоверсии с одинаковым префиксом базовой версии сортируются в хронологическом порядке.
Команда go выполняет несколько проверок, чтобы убедиться, что авторы модулей контролируют сравнение псевдоверсий с другими версиями и что псевдоверсии ссылаются на ревизии, которые действительно являются частью истории коммитов модуля.
- Если указана базовая версия, должен быть соответствующий семантический тег версии, который является предком ревизии, описанной псевдоверсией. Это предотвращает обход минимального выбора версии разработчиками с помощью псевдоверсии, которая сравнивается выше всех тегированных версий, таких как
v1.999.999-99999999999999-daa7c04131f5
. - Временная метка должна совпадать с временной меткой ревизии. Это предотвращает затопление прокси-серверов модулей неограниченным количеством идентичных псевдоверсий. Это также предотвращает изменение относительного порядка версий потребителями модулей.
- Ревизия должна быть предком одной из веток или тегов репозитория модуля. Это предотвращает ссылки злоумышленников на не утвержденные изменения или запросы на извлечение.
Псевдоверсии никогда не нужно вводить вручную. Многие команды принимают хэш коммита или имя ветки и автоматически преобразуют его в псевдоверсию (или версию с тегом, если она доступна).
Например:
go get example.com/mod@master
go list -m -json example.com/mod@abcd1234
Суффиксы основных версий
Начиная с основной версии 2
, пути к модулям должны иметь суффикс основной версии, такой как /v2
, который соответствует основной версии. Например, если модуль имеет путь example.com/mod
в версии v1.0.0
, он должен иметь путь example.com/mod/v2
в версии v2.0.0
.
Суффиксы основных версий реализуют правило совместимости импорта:
- Если старый пакет и новый пакет имеют одинаковый путь импорта, новый пакет должен быть обратно совместим со старым пакетом.
По определению, пакеты в новой основной версии модуля не являются обратно совместимыми с соответствующими пакетами в предыдущей основной версии. Следовательно, начиная с v2
, пакетам требуются новые пути импорта. Это достигается путем добавления суффикса основной версии к пути модуля.
Поскольку путь модуля является префиксом пути импорта для каждого пакета в модуле, добавление суффикса основной версии к пути модуля обеспечивает отдельный путь импорта для каждой несовместимой версии.
Суффиксы основной версии не допускаются в основных версиях v0
или v1
. Нет необходимости изменять путь модуля между v0
и v1
, поскольку версии v0
нестабильны и не имеют гарантии совместимости. Кроме того, для большинства модулей v1
обратно совместима с последней версией v0
; версия v1
действует как обязательство по совместимости, а не как указание на несовместимые изменения по сравнению с v0
.
В качестве особого случая пути модулей, начинающиеся с gopkg.in/
, всегда должны иметь суффикс основной версии, даже в v0
и v1
. Суффикс должен начинаться с точки, а не с косой черты (например, gopkg.in/yaml.v2
).
Суффиксы основных версий позволяют нескольким основным версиям модуля сосуществовать в одной сборке. Это может быть необходимо из-за проблемы алмазной зависимости.
Обычно, если модуль требуется в двух разных версиях по транзитивным зависимостям, будет использоваться более высокая версия. Однако, если две версии несовместимы, ни одна из них не удовлетворит всех клиентов.
Поскольку несовместимые версии должны иметь разные номера основных версий, они также должны иметь разные пути модулей из-за суффиксов основных версий. Это разрешает конфликт: модули с разными суффиксами рассматриваются как отдельные модули, и их пакеты — даже пакеты в одном и том же подкаталоге относительно корней модулей — являются разными.
Многие проекты Go выпускали версии v2
или выше без использования суффикса основной версии до перехода на модули (возможно, даже до того, как модули были введены). Эти версии помечены тегом +incompatible build
(например, v2.0.0+incompatible
). Дополнительную информацию см. в разделе «Совместимость с репозиториями, не являющимися модулями».
Преобразование пакета в модуль
Когда команда go
загружает пакет, используя путь к пакету, ей необходимо определить, какой модуль предоставляет этот пакет.
Команда go
начинает с поиска в списке сборки модулей с путями, которые являются префиксами пути пакета.
Например, если импортирован пакет example.com/a/b
, а модуль example.com/a
находится в списке сборки, команда go проверит, содержит ли example.com/a
пакет в каталоге b
.
Чтобы каталог считался пакетом, в нем должен присутствовать хотя бы один файл с расширением .go. Ограничения сборки для этой цели не применяются. Если ровно один модуль в списке сборки предоставляет пакет, используется этот модуль. Если ни один модуль не предоставляет пакет или если два или более модулей предоставляют пакет, команда go
сообщает об ошибке.
Флаг -mod=mod указывает команде go попытаться найти новые модули, предоставляющие отсутствующие пакеты, и обновить go.mod
и go.sum. Команды go get и go mod tidy делают это автоматически.
Когда команда go
ищет новый модуль для пути пакета, она проверяет переменную окружения GOPROXY
, которая представляет собой разделенный запятыми список URL-адресов прокси или ключевые слова direct
или off
. URL-адрес прокси указывает, что команда go должна связаться с прокси модуля, используя протокол GOPROXY
. direct
указывает, что команда go
должна связываться с системой контроля версий. off
указывает, что попытки связи не должны предприниматься. Переменные окружения GOPRIVATE
и GONOPROXY
также могут использоваться для управления этим поведением.
Для каждой записи в списке GOPROXY
команда go
запрашивает последнюю версию каждого пути модуля, который может предоставить пакет (то есть каждый префикс пути пакета). Для каждого успешно запрошенного пути модуля команда go загрузит модуль в последней версии и проверит, содержит ли модуль запрошенный пакет. Если один или несколько модулей содержат запрошенный пакет, используется модуль с самым длинным путем. Если найден один или несколько модулей, но ни один из них не содержит запрошенный пакет, выводится сообщение об ошибке. Если модули не найдены, команда go
пробует следующую запись в списке GOPROXY
. Если записей не осталось, выводится сообщение об ошибке.
Например, предположим, что команда
go
ищет модуль, который предоставляет пакетgolang.org/x/net/html
, аGOPROXY
установлен наhttps://corp.example.com,https://proxy.golang.org
. Командаgo
может сделать следующие запросы:
- К
https://corp.example.com/
(параллельно):- Запрос на последнюю версию
golang.org/x/net/html
- Запрос на последнюю версию
golang.org/x/net
- Запрос на последнюю версию
golang.org/x
- Запрос на последнюю версию
golang.org
- Запрос на последнюю версию
- К
https://proxy.golang.org/
, если все запросы кhttps://corp.example.com/
завершились с ошибкой 404 или 410:- Запрос на последнюю версию
golang.org/x/net/html
- Запрос на последнюю версию
golang.org/x/net
- Запрос на последнюю версию
golang.org/x
- Запрос на последнюю версию
golang.org
- Запрос на последнюю версию
После того, как подходящий модуль найден, команда go добавляет новое требование с путем и версией нового модуля в файл go.mod
основного модуля. Это гарантирует, что при загрузке того же пакета в будущем будет использоваться тот же модуль той же версии. Если разрешенный пакет не импортируется пакетом в основном модуле, новое требование будет иметь //
косвенный комментарий.
Файлы go.mod
Модуль определяется текстовым файлом go.mod
в кодировке UTF-8 в его корневом каталоге. Файл go.mod
ориентирован на строки. Каждая строка содержит одну директиву, состоящую из ключевого слова и аргументов.
Например:
module example.com/my/thing
go 1.23.0
require example.com/other/thing v1.0.2
require example.com/new/thing/v2 v2.3.4
exclude example.com/old/thing v1.2.3
replace example.com/bad/thing v1.4.5 => example.com/good/thing v1.4.5
retract [v1.9.0, v1.9.5]
Ведущее ключевое слово может быть разложено на соседние строки, чтобы создать блок, как в импорте Go.
require (
example.com/new/thing/v2 v2.3.4
example.com/old/thing v1.2.3
)
Файл go.mod
разработан таким образом, чтобы его можно было читать и записывать. Команда go
предоставляет несколько подкоманд, которые изменяют файлы go.mod
. Например, go get
может обновить или понизить уровень определенных зависимостей.
Команды, загружающие граф модулей, автоматически обновляют go.mod
, когда это необходимо. go mod edit
может выполнять низкоуровневые правки. Пакет golang.org/x/mod/modfile
может быть использован программами на Go для внесения тех же изменений программно.
Файл go.mod
требуется для основного модуля и для любого заменяющего его модуля, указанного с помощью локального пути к файлу. Однако модуль, не имеющий явного файла go.mod
, все равно может быть востребован в качестве зависимости или использоваться в качестве замены, указанной с помощью пути к модулю и его версии; см. раздел Совместимость с немодульными репозиториями.
Лексические элементы
При разборе файла go.mod
его содержимое разбивается на последовательность токенов. Существует несколько видов токенов: пробелы
, комментарии
, знаки препинания
, ключевые слова
, идентификаторы
и строки
.
Пробелы состоят из пробелов (U+0020)
, табуляции (U+0009)
, возврата каретки (U+000D)
и новой строки (U+000A)
. Пробелы, кроме новой строки, не имеют никакого эффекта, кроме разделения токенов, которые в противном случае были бы объединены. Новые строки являются значимыми токенами.
Комментарии начинаются с //
и продолжаются до конца строки. Комментарии /* */
не допускаются.
Знаки препинания включают (
, )
и =>
.
Ключевые слова различают различные типы директив в файле go.mod
. Допустимые ключевые слова: module
, go
, require
, replace
, exclude
и retract
.
Идентификаторы — это последовательности символов, не являющихся пробелами, такие как пути модулей или семантические версии.
Строки — это последовательности символов в кавычках. Существует два вида строк: интерпретируемые строки, начинающиеся и заканчивающиеся кавычками (", U+0022)
, и необработанные строки, начинающиеся и заканчивающиеся грависными акцентами (`, U+0060). Интерпретируемые строки могут содержать экранирующие последовательности, состоящие из обратной косой черты (\, U+005C)
, за которой следует другой символ. Экранированная кавычка (\») не завершает интерпретируемую строку. Незаключенное в кавычки значение интерпретируемой строки — это последовательность символов между кавычками, в которой каждая экранирующая последовательность заменяется символом, следующим за обратной косой чертой (например, \"
заменяется на "
, \n
заменяется на n
). Напротив, незаключенное в кавычки значение необработанной строки — это просто последовательность символов между грависами; обратные косые черты не имеют особого значения в необработанных строках.
Идентификаторы и строки взаимозаменяемы в грамматике go.mod
.
Пути к модулям и версии
Большинство идентификаторов и строк в файле go.mod
являются либо путями к модулям, либо версиями.
Путь к модулю должен удовлетворять следующим требованиям:
- Путь должен состоять из одного или нескольких элементов, разделенных косыми чертами
(/, U+002F)
. Он не должен начинаться или заканчиваться косой чертой. - Каждый элемент пути представляет собой непустую строку, состоящую из букв
ASCII
, цифрASCII
и ограниченного набора знаков препинанияASCII
(-
,.
,_
и~
). - Элемент пути не может начинаться или заканчиваться точкой
(., U+002E)
. - Префикс элемента до первой точки не должен быть зарезервированным именем файла в Windows, независимо от регистра (CON, com1, NuL и т. д.).
- Префикс элемента до первой точки не должен заканчиваться на тильду, за которой следует одна или несколько цифр (например, EXAMPL~1.COM).
Если путь к модулю появляется в директиве require
и не заменяется, или если путь к модулю появляется в правой части директивы replace
, команде go
может потребоваться загрузить модули с этим путем, и должны быть выполнены некоторые дополнительные требования.
- Ведущий элемент пути (до первой косой черты, если она есть), по соглашению являющийся доменным именем, должен содержать только строчные буквы ASCII, цифры ASCII, точки (., U+002E) и тире (-, U+002D); он должен содержать по крайней мере одну точку и не может начинаться с тире.
- Для конечного элемента пути в форме /vN, где N выглядит как число (цифры ASCII и точки), N не должно начинаться с нуля, не должно быть /v1 и не должно содержать точек.
- Для путей, начинающихся с gopkg.in/, это требование заменяется требованием, чтобы путь соответствовал соглашениям службы gopkg.in.
Версии в файлах
go.mod
могут быть каноническими или неканоническими.
- Для путей, начинающихся с gopkg.in/, это требование заменяется требованием, чтобы путь соответствовал соглашениям службы gopkg.in.
Версии в файлах
Каноническая версия начинается с буквы v, за которой следует семантическая версия, соответствующая спецификации Semantic Versioning 2.0.0. Дополнительные сведения см. в разделе «Версии».
Большинство других идентификаторов и строк могут использоваться в качестве неканонических версий, хотя существуют некоторые ограничения, позволяющие избежать проблем с файловыми системами, репозиториями и прокси-серверами модулей. Неканонические версии допускаются только в файле go.mod
главного модуля. Команда go
попытается заменить каждую неканоническую версию эквивалентной канонической версией при автоматическом обновлении файла go.mod
.
В местах, где путь модуля связан с версией (как в директивах require
, replace
и exclude
), конечный элемент пути должен соответствовать версии. См. Суффиксы основных версий.
Грамматика
Синтаксис go.mod
указан ниже с использованием расширенной формы Бэкуса-Наура (EBNF
). Подробнее о синтаксисе EBNF
см. раздел “Нотация” в спецификации языка Go
.
GoMod = { Directive } .
Directive = ModuleDirective |
GoDirective |
ToolDirective |
IgnoreDirective |
RequireDirective |
ExcludeDirective |
ReplaceDirective |
RetractDirective .
Новая строка, идентификаторы и строки обозначаются символами newline
, ident
и string
, соответственно.
Пути и версии модулей обозначаются ModulePath
и Version
.
ModulePath = ident | string . /* см. ограничения выше */
Версия = ident | string . /* см. ограничения выше */
module
директива
Директива module
определяет путь к главному модулю. Файл go.mod
должен содержать ровно одну директиву модуля.
Например:
module golang.org/x/net
Deprecation (Устаревший)
Модуль может быть помечен как устаревший в блоке комментариев, содержащем строку Deprecated
: (с учетом регистра) в начале абзаца. Сообщение об устаревании начинается после двоеточия и идет до конца абзаца. Комментарии могут располагаться непосредственно перед директивой модуля или после нее в той же строке.
Например:
// Deprecated: use example.com/mod/v2 instead.
module example.com/mod
Начиная с Go 1.17, go list -m -u
проверяет информацию обо всех устаревших модулях в списке сборки. go get
проверяет устаревшие модули, необходимые для сборки пакетов, указанных в командной строке.
Когда команда go
извлекает информацию об устаревании модуля, она загружает файл go.mod
из версии, соответствующей запросу @latest
, без учета отзывов или исключений. Команда go загружает список отозванных версий из того же файла go.mod
.
Чтобы объявить модуль устаревшим, автор может добавить комментарий // Deprecated
: и пометить новый выпуск. Автор может изменить или удалить сообщение об устаревании в более позднем выпуске.
Устаревание применяется ко всем второстепенным версиям модуля. Основные версии выше v2
считаются отдельными модулями для этой цели, поскольку их суффиксы основных версий дают им отличные пути модулей.
Сообщения об устаревании предназначены для информирования пользователей о том, что модуль больше не поддерживается, и для предоставления инструкций по миграции, например, на последнюю основную версию. Отдельные второстепенные и исправленные версии не могут быть признаны устаревшими; для этого более подходящим может быть отзыв.
go
директива
Директива go
указывает, что модуль был написан с учетом семантики определенной версии Go. Версия должна быть действительной версией Go, например 1.14, 1.21rc1 или 1.23.0.
Директива go
устанавливает минимальную версию Go, необходимую для использования этого модуля. До Go 1.21 эта директива носила только рекомендательный характер, теперь же она является обязательным требованием: инструментарий Go отказывается использовать модули, объявляющие более новые версии Go.
Директива go
является входными данными для выбора инструментария Go, который будет запущен. Подробности см. в разделе «Инструментарий Go».
Директива go
влияет на использование новых языковых функций:
- Для пакетов в модуле компилятор отклоняет использование языковых функций, введенных после версии, указанной в директиве
go
. Например, если модуль имеет директивуgo 1.12
, его пакеты не могут использовать числовые литералы, такие как1_000_000
, которые были введены в Go 1.13. - Если более старая версия Go компилирует один из пакетов модуля и встречает ошибку компиляции, в сообщении об ошибке указывается, что модуль был написан для более новой версии Go. Например, предположим, что модуль имеет директиву
go 1.13
, а пакет использует числовой литерал1_000_000
. Если этот пакет компилируется с помощью Go 1.12, компилятор отмечает, что код написан для Go 1.13.
Директива go
также влияет на поведение команды go
:
-
В go 1.14 и выше может быть включена автоматическая продажа. Если файл
vendor/modules.txt
присутствует и соответствуетgo.mod
, нет необходимости явно использовать флаг-mod=vendor
. -
В go 1.16 и выше шаблон
all
package соответствует только пакетам, транзитивно импортированным пакетами и тестами в главном модуле. Это тот же набор пакетов, который сохраняетсяgo mod vendor
с момента введения модулей. В более ранних версияхall
также включает тесты пакетов, импортированных пакетами в главном модуле, тесты этих пакетов и т. д. -
В go 1.17 и выше:
- Файл
go.mod
включает явную директиву require для каждого модуля, который предоставляет любой пакет, транзитивно импортированный пакетом или тестом в главном модуле. (В go 1.16 и ниже косвенная зависимость включается только в том случае, если при выборе минимальной версии в противном случае была бы выбрана другая версия.) Эта дополнительная информация позволяет выполнять обрезку графа модулей и отложенную загрузку модулей. - Поскольку
//
косвенных зависимостей может быть гораздо больше, чем в предыдущих версияхgo
, косвенные зависимости записываются в отдельном блоке в файлеgo.mod
. go mod vendor
опускает файлыgo.mod
иgo.sum
для зависимостей, поставляемых поставщиком. (Это позволяет вызывать командуgo
в подкаталогахvendor
для определения правильного основного модуля.)go mod vendor
записывает версиюgo
из файлаgo.mod
каждой зависимости вvendor/modules.txt
.
- Файл
-
В go 1.21 или выше:
- Строка
go
объявляет минимальную версию Go, необходимую для использования с этим модулем. - Строка
go
должна быть больше или равна строке go всех зависимостей. - Команда
go
больше не пытается поддерживать совместимость с предыдущей старой версией Go. - Команда
go
более тщательно следит за сохранением контрольных сумм файловgo.mod
в файлеgo.sum
.
- Строка
Файл go.mod
может содержать не более одной директивы go
. Большинство команд добавляют директиву go
с текущей версией Go, если она отсутствует.
Если директива go
отсутствует, предполагается, что используется go 1.16
.
GoDirective = «go» GoVersion newline .
GoVersion = string | ident . /* действительная версия выпуска; см. выше */
Пример:
go 1.23.0
toolchain
директива
Директива toolchain
объявляет предлагаемую цепочку инструментов Go для использования с модулем. Версия предлагаемой цепочки инструментов Go не может быть меньше требуемой версии Go, объявленной в директиве go
. Директива toolchain
действует только в том случае, если модуль является главным модулем и версия инструментальной цепочки по умолчанию меньше версии предлагаемой инструментальной цепочки.
Для воспроизводимости команда go
записывает собственное имя цепочки инструментов в строку toolchain
каждый раз, когда обновляет версию go в файле go.mod
(обычно во время go get
).
Подробности см. в разделе “Инструментальные цепочки Go”.
ToolchainDirective = "toolchain" ToolchainName newline .
ToolchainName = string | ident . /* действительное имя цепочки инструментов; см. "Цепочки инструментов Go" */
Пример:
toolchain go1.21.0
godebug
деректива
Директива godebug
объявляет единственную настройку GODEBUG
, которая должна применяться, когда данный модуль является основным. Таких строк может быть несколько, и они могут быть разделены по факторам. Ошибкой является то, что главный модуль называет несуществующий ключ GODEBUG
. Эффект от применения godebug key=value
такой, как если бы каждый компилируемый основной пакет содержал исходный файл, в котором был бы указан //go:debug key=value
.
GodebugDirective = "godebug" ( GodebugSpec | "(" newline { GodebugSpec } ")" newline ) .
GodebugSpec = GodebugKey "=" GodebugValue newline.
GodebugKey = GodebugChar { GodebugChar }.
GodebugValue = GodebugChar { GodebugChar }.
GodebugChar = any non-space character except , " ` ' (comma and quotes).
Например:
godebug default=go1.21
godebug (
panicnil=1
asynctimerchan=0
)
require
директива
Директива require
объявляет минимальную требуемую версию данной зависимости модуля. Для каждой требуемой версии модуля команда go
загружает файл go.mod
для этой версии и включает требования из этого файла. После загрузки всех требований команда go
разрешает их с помощью минимального выбора версии (MVS)
для создания списка сборки.
Команда go
автоматически добавляет //
косвенные комментарии для некоторых требований. Косвенный комментарий //
указывает, что ни один пакет из требуемого модуля не импортируется напрямую каким-либо пакетом в основном модуле.
Если директива go
указывает go 1.16
или ниже, команда go
добавляет косвенное требование, когда выбранная версия модуля выше, чем то, что уже подразумевается (транзитивно) другими зависимостями основного модуля. Это может произойти из-за явного обновления (go get -u ./...
), удаления какой-либо другой зависимости, которая ранее налагала требование (go mod tidy
), или зависимости, которая импортирует пакет без соответствующего требования в своем собственном файле go.mod
(например, зависимость, у которой вообще отсутствует файл go.mod
).
В go 1.17
и выше команда go
добавляет косвенное требование для каждого модуля, который предоставляет любой пакет, импортируемый (даже косвенно) пакетом или тестом в основном модуле или передаваемый в качестве аргумента go get
. Эти более комплексные требования позволяют выполнять обрезку графа модулей и отложенную загрузку модулей.
RequireDirective = "require" ( RequireSpec | "(" newline { RequireSpec } ")" newline ) .
RequireSpec = ModulePath Version newline .
Например:
require golang.org/x/net v1.2.3
require (
golang.org/x/crypto v1.4.5 // indirect
golang.org/x/text v1.6.7
)
tool
директива
Директива tool
добавляет пакет в качестве зависимости от текущего модуля. Она также делает его доступным для запуска с помощью инструмента go
, если текущий рабочий каталог находится в этом модуле или в рабочей области, содержащей этот модуль.
Если пакет инструмента не находится в текущем модуле, должна присутствовать директива require
, указывающая версию используемого инструмента.
Меташаблон tool
разрешается в список инструментов, определенных в go.mod
текущего модуля, или в режиме рабочего пространства - в объединение всех инструментов, определенных во всех модулях рабочего пространства.
ToolDirective = "tool" ( ToolSpec | "(" newline { ToolSpec } ")" newline ) .
ToolSpec = ModulePath newline .
Например:
tool golang.org/x/tools/cmd/stringer
tool (
example.com/module/cmd/a
example.com/module/cmd/b
)
ignore
директива
Директива ignore
заставляет команду go
игнорировать разделенные косой чертой пути к каталогам, а также любые файлы или каталоги, рекурсивно содержащиеся в них, при поиске шаблонов пакетов.
Если путь начинается с ./
, то он интерпретируется относительно корневого каталога модуля, и этот каталог и любые каталоги или файлы, рекурсивно содержащиеся в нем, будут игнорироваться при поиске шаблонов пакетов.
В противном случае все каталоги с таким путем на любой глубине модуля и любые каталоги или файлы, рекурсивно содержащиеся в них, будут проигнорированы.
Например:
ignore ./node_modules
ignore (
static
content/html
./third_party/javascript
)
exclude
директива
Директива exclude
предотвращает загрузку версии модуля командой go
.
Начиная с Go 1.16, если версия, на которую ссылается директива require
в любом файле go.mod
, исключена директивой exclude
в файле go.mod
основного модуля, требование игнорируется. Это может привести к тому, что команды go get
и go mod tidy
добавят новые требования к более высоким версиям в go.mod
с //
косвенным комментарием, если это уместно.
До Go 1.16, если исключенная версия была указана директивой require
, команда go
перечисляла доступные версии для модуля (как показано с помощью go list -m -versions
) и загружала следующую более высокую неисключенную версию. Это могло привести к недетерминированному выбору версии, поскольку следующая более высокая версия могла измениться со временем. Для этой цели учитывались как релизные, так и предрелизные версии, но не учитывались псевдоверсии. Если более высоких версий не было, команда go
сообщала об ошибке.
Директивы exclude
применяются только в файле go.mod
основного модуля и игнорируются в других модулях. Подробности см. в разделе «Минимальный выбор версии».
ExcludeDirective = "exclude" ( ExcludeSpec | "(" newline { ExcludeSpec } ")" newline ) .
ExcludeSpec = ModulePath Version newline .
Например:
exclude golang.org/x/net v1.2.3
exclude (
golang.org/x/crypto v1.4.5
golang.org/x/text v1.6.7
)
replace
директива
Директива replace
заменяет содержимое определенной версии модуля или всех версий модуля содержимым, найденным в другом месте. Замена может быть указана либо другим путем к модулю и версии, либо путем к файлу, специфичному для платформы.
Если версия указана слева от стрелки (=>)
, заменяется только эта конкретная версия модуля; доступ к другим версиям будет осуществляться в обычном режиме. Если левая версия опущена, заменяются все версии модуля.
Если путь справа от стрелки является абсолютным или относительным (начинается с ./
или ../
), он интерпретируется как локальный путь к корневому каталогу модуля замены, который должен содержать файл go.mod
. В этом случае версия замены должна быть опущена.
Если путь справа не является локальным путем, он должен быть действительным путем к модулю. В этом случае требуется указать версию. Та же версия модуля не должна также фигурировать в списке сборки.
Независимо от того, указана ли замена с помощью локального пути или пути к модулю, если модуль замены имеет файл go.mod
, его директива модуля должна соответствовать пути к модулю, который он заменяет.
Директивы replace
применяются только в файле go.mod
главного модуля и игнорируются в других модулях. Подробности см. в разделе «Выбор минимальной версии».
Если есть несколько главных модулей, применяются файлы go.mod
всех главных модулей. Конфликтующие директивы replace
между главными модулями не допускаются и должны быть удалены или переопределены в replace
в файле go.work
.
Обратите внимание, что сама по себе директива replace
не добавляет модуль в граф модулей. Также необходима директива require
, которая ссылается на замененную версию модуля, либо в файле go.mod
основного модуля, либо в файле go.mod
зависимости. Директива replace
не имеет эффекта, если версия модуля слева не требуется.
ReplaceDirective = "replace" ( ReplaceSpec | "(" newline { ReplaceSpec } ")" newline ) .
ReplaceSpec = ModulePath [ Version ] "=>" FilePath newline
| ModulePath [ Version ] "=>" ModulePath Version newline .
FilePath = /* platform-specific relative or absolute file path */
Например:
replace golang.org/x/net v1.2.3 => example.com/fork/net v1.4.5
replace (
golang.org/x/net v1.2.3 => example.com/fork/net v1.4.5
golang.org/x/net => example.com/fork/net v1.4.5
golang.org/x/net v1.2.3 => ./fork/net
golang.org/x/net => ./fork/net
)
retract
директива
Директива retract
указывает, что версия или диапазон версий модуля, определенные в go.mod
, не должны использоваться. Директива retract
полезна, когда версия была опубликована преждевременно или после публикации версии была обнаружена серьезная проблема. Отмененные версии должны оставаться доступными в репозиториях контроля версий и на прокси-серверах модулей, чтобы обеспечить работоспособность сборок, которые от них зависят. Слово retract
заимствовано из академической литературы: отмененная научная статья по-прежнему доступна, но в ней есть проблемы, и она не должна служить основой для будущих работ.
Когда версия модуля отзывается, пользователи не будут автоматически обновляться до нее с помощью go get
, go mod tidy
или других команд. Сборки, которые зависят от отозванных версий, должны продолжать работать, но пользователи будут уведомлены об отзывах, когда они будут проверять обновления с помощью go list -m -u
или обновлять связанный модуль с помощью go get
.
Чтобы отозвать версию, автор модуля должен добавить директиву retract
в go.mod
, а затем опубликовать новую версию, содержащую эту директиву. Новая версия должна быть выше других выпущенных или предварительных версий; то есть запрос @latest version
должен возвращать новую версию, прежде чем будут рассмотрены отзывы. Команда go
загружает и применяет отзывы из версии, показанной командой go list -m -retracted $modpath@latest
(где $modpath
— путь к модулю).
Отмененные версии скрываются из списка версий, выводимого командой go list -m -versions
, если не используется флаг -retracted
. Отмененные версии исключаются при разрешении запросов версий, таких как @>=v1.2.3
или @latest
.
Версия, содержащая отмены, может отменить себя. Если самая высокая релизная или предрелизная версия модуля отменяет себя, запрос @latest
разрешается в более низкую версию после исключения отмененных версий.
В качестве примера рассмотрим случай, когда автор модуля example.com/m
случайно публикует версию v1.0.0
. Чтобы пользователи не обновлялись до v1.0.0
, автор может добавить две директивы retract
в go.mod
, а затем пометить v1.0.1
с отзывами.
retract (
v1.0.0 // Опубликовано случайно.
v1.0.1 // Содержит только отмены.)
Когда пользователь запускает go get example.com/m@latest
, команда go
считывает отмены из v1.0.1
, которая теперь является самой высокой версией. И v1.0.0
, и v1.0.1
отменены, поэтому команда go
обновит (или понизит!) версию до следующей самой высокой версии, возможно v0.9.5
.
Директивы retract
могут быть написаны с одной версией (например, v1.0.0
) или с закрытым интервалом версий с верхней и нижней границами, ограниченными символами [
и ]
(например, [v1.1.0, v1.2.0]
). Одна версия эквивалентна интервалу, где верхняя и нижняя границы одинаковы. Как и другие директивы, несколько директив retract
могут быть сгруппированы в блок, ограниченный символами (
в конце строки и )
в отдельной строке.
Каждая директива retract
должна иметь комментарий, объясняющий причину отзыва, хотя это не является обязательным. Команда go может отображать комментарии с объяснением причин в предупреждениях об отозванных версиях и в выводе go list
. Комментарий с обоснованием может быть написан непосредственно над директивой retract
(без пробела между ними) или после нее в той же строке. Если комментарий находится над блоком, он применяется ко всем директивам retract
в блоке, которые не имеют собственных комментариев. Комментарий с обоснованием может занимать несколько строк.
RetractDirective = "retract" ( RetractSpec | "(" newline { RetractSpec } ")" newline ) .
RetractSpec = ( Version | "[" Version "," Version "]" ) newline .
Примеры:
- Извлечение всех версий между v1.0.0 и v1.9.9:
retract v1.0.0
retract [v1.0.0, v1.9.9]
retract (
v1.0.0
[v1.0.0, v1.9.9]
)
- Возврат к предварительной версии после преждевременного выпуска версии v1.0.0:
retract [v0.0.0, v1.0.1] // assuming v1.0.1 contains this retraction.
- Стирание модуля, включая все псевдо-версии и помеченные версии:
retract [v0.0.0-0, v0.15.2] // assuming v0.15.2 contains this retraction.
Директива retract
была добавлена в Go 1.16. Go 1.15 и ниже сообщает об ошибке, если директива retract
записана в файле go.mod
главного модуля, и игнорирует директивы retract
в файлах go.mod
зависимых модулей.
Автоматические обновления
Большинство команд сообщают об ошибке, если в go.mod
отсутствует информация или он не совсем точно отражает реальность. Команды go get
и go mod tidy
могут быть использованы для устранения большинства этих проблем. Кроме того, флаг -mod=mod
можно использовать с большинством команд с поддержкой модулей (go build
, go test
и т. д.), чтобы указать команде go
исправить проблемы в go.mod
и go.sum
автоматически.
Например, рассмотрим этот файл
go.mod
:
module example.com/M
go 1.23.0
require (
example.com/A v1
example.com/B v1.0.0
example.com/C v1.0.0
example.com/D v1.2.3
example.com/E dev
)
exclude example.com/D v1.2.3
Обновление, запущенное с помощью -mod=mod
, переписывает неканонические идентификаторы версий в каноническую форму semver
, поэтому v1 example.com/A
становится v1.0.0
, а dev example.com/E
становится псевдоверсией для последней фиксации в ветке dev
, возможно, v0.0. 0-20180523231146-b3f5c0f6e5f1
.
Обновление изменяет требования с учетом исключений, поэтому требование к исключенному example.com/D v1.2.3
обновляется для использования следующей доступной версии example.com/D
, возможно, v1.2.4
или v1.3.0
.
Обновление удаляет избыточные или вводящие в заблуждение требования. Например, если example.com/A v1.0.0
сам требует example.com/B v1.2.0
и example.com/C v1.0.0
, то требование go.mod
к example.com/B v1.0.0
вводит в заблуждение (заменяется требованием example.com/A к v1.2.0
), а его требование к example. com/C v1.0.0
является избыточным (поскольку example.com/A
требует ту же версию), поэтому оба требования будут удалены. Если основной модуль содержит пакеты, которые напрямую импортируют пакеты из example.com/B
или example.com/C
, то требования будут сохранены, но обновлены до фактически используемых версий.
Наконец, обновление переформатирует go.mod
в каноническом формате, так что будущие механические изменения приведут к минимальным различиям. Команда go
не будет обновлять go.mod
, если требуются только изменения форматирования.
Поскольку граф модулей определяет значение операторов import
, любые команды, которые загружают пакеты, также используют go.mod
и поэтому могут его обновлять, включая go build
, go get
, go install
, go list
, go test
, go mod tidy
.
В Go 1.15 и ниже флаг -mod=mod
был включен по умолчанию, поэтому обновления выполнялись автоматически. Начиная с Go 1.16, команда go
действует так, как если бы был установлен флаг -mod=readonly
: если требуются какие-либо изменения в go.mod
, команда go
сообщает об ошибке и предлагает исправление.
Выбор минимальной версии (MVS)
Go использует алгоритм под названием «Выбор минимальной версии» (MVS)
для выбора набора версий модулей, которые будут использоваться при сборке пакетов. MVS
подробно описан в статье «Выбор минимальной версии» Расса Кокса.
Концептуально MVS
работает с направленным графом модулей, указанным в файлах go.mod
. Каждая вершина графа представляет версию модуля. Каждая ребро представляет минимальную требуемую версию зависимости, указанную с помощью директивы require
. Граф может быть изменен с помощью директив exclude
и replace
в файлах go.mod
основных модулей и с помощью директив replace
в файле go.work
.
MVS
генерирует список сборок в качестве вывода, то есть список версий модулей, используемых для сборки.
MVS
начинает с основных модулей (специальных вершин в графе, не имеющих версии) и проходит по графу, отслеживая наивысшую требуемую версию каждого модуля. В конце прохождения наивысшие требуемые версии составляют список сборок: это минимальные версии, удовлетворяющие всем требованиям.
Список сборки можно просмотреть с помощью команды go list -m all
. В отличие от других систем управления зависимостями, список сборки не сохраняется в файле «lock
». MVS
является детерминированным, и список сборки не изменяется при выпуске новых версий зависимостей, поэтому MVS
используется для его вычисления в начале каждой команды, учитывающей модули.
Рассмотрим пример на диаграмме ниже. Основной модуль требует модуль A
версии 1.2 или выше и модуль B
версии 1.2 или выше. A 1.2
и B 1.2
требуют C 1.3
и C 1.4
соответственно. C 1.3
и C 1.4
требуют D 1.2
.
MVS
посещает и загружает файл go.mod
для каждой из версий модуля, выделенных синим цветом. В конце обхода графа MVS
возвращает список сборок, содержащий выделенные жирным шрифтом версии: A 1.2
, B 1.2
, C 1.4
и D 1.2
. Обратите внимание, что доступны более высокие версии B
и D
, но MVS
не выбирает их, поскольку они не требуются.
Replacement (Замена)
Содержимое модуля (включая его файл go.mod
) может быть заменено с помощью директивы replace
в файле go.mod
главного модуля или в файле go.work рабочего пространства. Директива replace
может применяться к определенной версии модуля или ко всем версиям модуля.
Замены изменяют граф модулей, так как заменяющий модуль может иметь другие зависимости, чем заменяемые версии.
Рассмотрим пример ниже, где C 1.4
был заменен на R
. R
зависит от D 1.3
, а не от D 1.2
, поэтому MVS
возвращает список сборки, содержащий A 1.2
, B 1.2
, C 1.4
(замененный на R
) и D 1.3
.
Exclusion (Исключение)
Модуль также может быть исключен из определенных версий с помощью директивы exclude
в файле go.mod
главного модуля.
Исключения также изменяют граф модулей. Когда версия исключается, она удаляется из графа модулей, а требования к ней перенаправляются на следующую более высокую версию.
Рассмотрим пример ниже. Версия C 1.3
была исключена. MVS
будет действовать так, как если бы A 1.2
требовал C 1.4
(следующую более высокую версию), а не C 1.3
.
Upgrades (Обновления)
Команда go get
может быть использована для обновления набора модулей. Чтобы выполнить обновление, команда go
изменяет граф модулей перед запуском MVS
, добавляя ребра от посещенных версий к обновленным.
Рассмотрим пример ниже. Модуль B
может быть обновлен с 1.2
до 1.3
, C
может быть обновлен с 1.3
до 1.4
, а D
может быть обновлен с 1.2
до 1.3
.
Обновления (и понижения) могут добавлять или удалять косвенные зависимости. В этом случае E 1.1
и F 1.1
появляются в списке сборки после обновления, поскольку E 1.1
требуется B 1.3
.
Чтобы сохранить обновления, команда go
обновляет требования в файле go.mod
. Она изменит требования к B
на версию 1.3
. Она также добавит требования к C 1.4
и D 1.3
с // косвенными комментариями
, поскольку в противном случае эти версии не были бы выбраны.
Downgrade
Команда go get
также может быть использована для понижения рейтинга набора модулей. Чтобы выполнить понижение, команда go
изменяет граф модулей, удаляя версии выше пониженных версий. Она также удаляет версии других модулей, которые зависят от удаленных версий, поскольку они могут быть несовместимы с пониженными версиями своих зависимостей. Если главный модуль требует версию модуля, удаленную в результате понижения, требование меняется на предыдущую версию, которая не была удалена. Если предыдущая версия недоступна, требование отменяется.
Рассмотрим приведенный ниже пример. Предположим, что была обнаружена проблема с C 1.4
, поэтому мы понижаем версию до C 1.3
. C 1.4
удаляется из графа модулей. B 1.2
также удаляется, поскольку для него требуется C 1.4
или выше. Требование главного модуля к B
изменяется на 1.1
.
go get
также может полностью удалить зависимости, используя суффикс @none
после аргумента. Это работает аналогично Downgrade
. Все версии именованного модуля удаляются из графа модулей.
Обрезка графа модулей
Если основной модуль находится на версии go 1.17
или выше, граф модулей, используемый для выбора минимальной версии, включает только непосредственные требования для каждой зависимости модуля, которая указывает go 1.17
или выше в своем собственном файле go.mod
, за исключением случаев, когда эта версия модуля также (транзитивно) требуется какой-либо другой зависимостью на версии go 1.16
или ниже. (Транзитивные зависимости зависимостей go 1.17
удаляются из графа модулей.)
Поскольку файл go.mod
go 1.17
включает директиву require
для каждой зависимости, необходимой для сборки любого пакета или теста в этом модуле, обрезанный граф модулей включает все зависимости, необходимые для сборки или тестирования пакетов в любой зависимости, явно требуемой основным модулем. Модуль, который не требуется для сборки какого-либо пакета или теста в данном модуле, не может повлиять на поведение его пакетов во время выполнения, поэтому зависимости, удаленные из графа модулей, могут вызвать только помехи между модулями, которые в противном случае не были бы связаны между собой.
Модули, требования которых были удалены, по-прежнему отображаются в графе модулей и по-прежнему отображаются в go list -m all
: их выбранные версии известны и четко определены, и пакеты могут быть загружены из этих модулей (например, как транзитивные зависимости тестов, загруженных из других модулей). Однако, поскольку команда go
не может легко определить, какие зависимости этих модулей удовлетворены, аргументы go build
и go test
не могут включать пакеты из модулей, требования которых были удалены. go get
продвигает модуль, содержащий каждый названный пакет, в явную зависимость, позволяя вызывать go build
или go test
для этого пакета.
Поскольку Go 1.16 и более ранние версии не поддерживали удаление графа модулей, полное транзитивное закрытие зависимостей — включая транзитивные зависимости go 1.17
— по-прежнему включено для каждого модуля, который указывает go 1.16
или ниже. (В go 1.16
и ниже файл go.mod
включает только прямые зависимости, поэтому для обеспечения включения всех косвенных зависимостей необходимо загрузить гораздо более крупный граф).
Файл go.sum
, записанный go mod tidy
для модуля по умолчанию, включает контрольные суммы, необходимые для версии Go, на одну ниже версии, указанной в директиве go
. Таким образом, модуль go 1.17
включает контрольные суммы, необходимые для полного графа модулей, загруженного Go 1.16, но модуль go 1.18
будет включать только контрольные суммы, необходимые для обрезанного графа модулей, загруженного Go 1.17. Флаг -compat
можно использовать для переопределения версии по умолчанию (например, для более агрессивной обрезки файла go.sum
в модуле go 1.17).
Более подробную информацию см. в документе по проектированию.
Ленивая загрузка модуля
Более полные требования, добавленные для обрезки графа модуля, также позволяют еще одну оптимизацию при работе внутри модуля. Если основной модуль находится на уровне go 1.17
или выше, команда go избегает загрузки полного графа модуля, пока (и если) это не требуется. Вместо этого она загружает только файл go.mod
главного модуля, а затем пытается загрузить пакеты, которые нужно собрать, используя только эти требования. Если импортируемый пакет (например, зависимость теста для пакета вне основного модуля) не найден среди этих требований, то остальная часть графа модулей загружается по требованию.
Если все импортируемые пакеты могут быть найдены без загрузки графа модулей, команда go загружает файлы go.mod
только для модулей, содержащих эти пакеты, и их требования сверяются с требованиями основного модуля, чтобы убедиться, что они локально согласованы. (Несоответствия могут возникнуть из-за слияния версий, ручного редактирования и изменений в модулях, которые были заменены с использованием путей локальной файловой системы).
Workspaces (Рабочие пространства)
Рабочее пространство - это набор модулей на диске, которые используются в качестве основных модулей при запуске минимального выбора версий (MVS
).
Рабочее пространство может быть объявлено в файле go.work
, в котором указываются относительные пути к каталогам модулей каждого из модулей рабочего пространства. Если файл go.work
отсутствует, рабочая область состоит из единственного модуля, содержащего текущий каталог.
Большинство подкоманд go
, работающих с модулями, работают с набором модулей, определяемым текущим рабочим пространством. go mod init
, go mod why
, go mod edit
, go mod tidy
, go mod vendor
и go get
всегда работают с одним основным модулем.
Команда определяет, находится ли она в контексте рабочего пространства, сначала изучив переменную окружения GOWORK
. Если GOWORK
имеет значение off
, команда будет находиться в одномодульном контексте.
Если она пуста или не указана, команда будет искать файл go.work
в текущем рабочем каталоге, а затем в последовательных родительских каталогах.
Если файл найден, команда будет работать в определенном ею рабочем пространстве; в противном случае рабочее пространство будет включать только модуль, содержащий рабочий каталог.
Если GOWORK
называет путь к существующему файлу, который заканчивается на .work
, режим рабочего пространства будет включен.
Любое другое значение является ошибкой. Вы можете использовать команду go env GOWORK
, чтобы определить, какой файл go.work
использует команда go
. go env GOWORK
будет пустой, если команда go
не находится в режиме рабочего пространства.
Файлы go.work
Рабочая область определяется текстовым файлом с кодировкой UTF-8 под названием go.work
. Файл go.work
ориентирован на строки. Каждая строка содержит одну директиву, состоящую из ключевого слова, за которым следуют аргументы. Например:
go 1.23.0
use ./my/first/thing
use ./my/second/thing
replace example.com/bad/thing v1.4.5 => example.com/good/thing v1.4.5
Как и в файлах go.mod
, начальное ключевое слово может быть вынесено из соседних строк для создания блока.
use (
./my/first/thing
./my/second/thing
)
Команда go
предоставляет несколько подкоманд для работы с файлами go.work
.
go work init
создает новые файлыgo.work
.go work use
добавляет каталоги модулей в файлgo.work
.go work edit
выполняет низкоуровневые изменения.
Пакет golang.org/x/mod/modfile
может использоваться программами Go для программного внесения тех же изменений.
Команда go
будет поддерживать файл go.work.sum
, который отслеживает хэши, используемые рабочим пространством, которые не находятся в файлах go.sum
модулей коллективного рабочего пространства.
Обычно не рекомендуется фиксировать файлы go.work
в системах контроля версий по двум причинам:
- Зарегистрированный файл
go.work
может переопределить собственный файлgo.work
разработчика из родительского каталога, что приведет к путанице, когда их директивы использования не будут применяться. - Зарегистрированный файл
go.work
может привести к тому, что система непрерывной интеграции(CI)
выберет и, следовательно, протестирует неправильные версии зависимостей модуля. СистемамCI
, как правило, не следует разрешать использовать файлgo.work
, чтобы они могли тестировать поведение модуля так, как он будет использоваться при необходимости другими модулями, где файлgo.work
внутри модуля не имеет никакого эффекта.
Тем не менее, в некоторых случаях фиксация файла go.work
имеет смысл. Например, когда модули в репозитории разрабатываются исключительно друг с другом, но не вместе с внешними модулями, у разработчика может не быть причин использовать другую комбинацию модулей в рабочей области. В этом случае автор модуля должен убедиться, что отдельные модули протестированы и выпущены надлежащим образом.
Лексические элементы
Лексические элементы в файлах go.work
определяются точно так же, как и в файлах go.mod
.
Грамматика
Синтаксис go.work
указан ниже с использованием расширенной формы Бэкуса-Наура (EBNF)
. Подробнее о синтаксисе EBNF см. раздел “Нотация” в спецификации языка Go.
GoWork = { Directive } .
Directive = GoDirective |
ToolchainDirective |
UseDirective |
ReplaceDirective .
Новая строка, идентификаторы и строки обозначаются символами newline
, ident
и string
, соответственно.
Пути и версии модулей обозначаются ModulePath
и Version
. Пути и версии модулей указываются точно так же, как и для файлов go.mod
.
ModulePath = ident | string . /* see restrictions above */
Version = ident | string . /* see restrictions above */
go
директива
Директива go необходима в правильном файле go.work
. Версия должна быть действительной версией релиза Go: целое положительное число, за которым следует точка и целое неотрицательное число (например, 1.18, 1.19).
Директива go
указывает на версию инструментария go
, с которым должен работать файл go.work
. Если в формат файла go.work
будут внесены изменения, будущие версии цепочки инструментов будут интерпретировать файл в соответствии с указанной версией.
Файл go.work
может содержать не более одной директивы go
.
GoDirective = "go" GoVersion newline .
GoVersion = string | ident . /* действительная версия релиза; см. выше */
Пример:
go 1.23.0
toolchain
директива
Директива toolchain
объявляет предлагаемую цепочку инструментов Go для использования в рабочем пространстве. Она действует только в том случае, если цепочка инструментов по умолчанию старше предлагаемой цепочки инструментов.
Подробнее см. в разделе “Цепочки инструментов Go”.
ToolchainDirective = "toolchain" ToolchainName newline .
ToolchainName = string | ident . /* действительное имя цепочки инструментов; см. раздел "Цепочки инструментов Go" */
Пример:
toolchain go1.21.0
godebug
директива
Директива godebug объявляет единственную настройку GODEBUG
, которая должна применяться при работе в этом рабочем пространстве. Синтаксис и действие такие же, как у директивы godebug в файле go.mod
. Когда рабочая область используется, директивы godebug в файлах go.mod
игнорируются.
use
директива
Директива use
добавляет модуль на диск к набору основных модулей в рабочей области. Ее аргумент - относительный путь к директории, содержащей файл go.mod
модуля. Директива use
не добавляет модули, содержащиеся в подкаталогах каталога-аргумента. Эти модули могут быть добавлены в каталог, содержащий их файл go.mod
, в отдельных директивах use
.
UseDirective = "use" ( UseSpec | "(" newline { UseSpec } ")" newline ) .
UseSpec = FilePath newline .
FilePath = /* platform-specific relative or absolute file path */
Например:
use ./mymod // example.com/mymod
use (
../othermod
./subdir/thirdmod
)
replace
директива
Подобно директиве replace
в файле go.mod
, директива replace
в файле go.work
заменяет содержимое определенной версии модуля или всех версий модуля на содержимое, найденное в другом месте. Директива replace
в go.work
отменяет замену в файле go.mod
для конкретной версии.
Директивы replace
в файлах go.work
переопределяют любые замены того же модуля или версии модуля в модулях рабочего пространства.
ReplaceDirective = "replace" ( ReplaceSpec | "(" newline { ReplaceSpec } ")" newline ) .
ReplaceSpec = ModulePath [ Version ] "=>" FilePath newline
| ModulePath [ Version ] "=>" ModulePath Version newline .
FilePath = /* platform-specific relative or absolute file path */
Например:
replace golang.org/x/net v1.2.3 => example.com/fork/net v1.4.5
replace (
golang.org/x/net v1.2.3 => example.com/fork/net v1.4.5
golang.org/x/net => example.com/fork/net v1.4.5
golang.org/x/net v1.2.3 => ./fork/net
golang.org/x/net => ./fork/net
)
Совместимость с немодульными репозиториями
Чтобы обеспечить плавный переход от GOPATH
к модулям, команда go
может загружать и собирать пакеты в модульно-ориентированном режиме из репозиториев, которые не перешли на модули, добавив файл go.mod
.
Когда команда go
загружает модуль заданной версии непосредственно из репозитория, она ищет URL репозитория для пути к модулю, сопоставляет версию с ревизией в репозитории, а затем извлекает архив репозитория с этой ревизией. Если путь модуля равен корневому пути репозитория, а корневой каталог репозитория не содержит файла go.mod
, команда go
синтезирует в кэше модулей файл go.mod
, содержащий директиву модуля и ничего больше. Поскольку синтетические файлы go.mod
не содержат директив require для своих зависимостей, другим модулям, зависящим от них, могут потребоваться дополнительные директивы require (с косвенными комментариями //
), чтобы гарантировать, что каждая зависимость будет получена в одной и той же версии при каждой сборке.
Когда команда go
загружает модуль с прокси, она загружает файл go.mod
отдельно от остального содержимого модуля. Предполагается, что прокси-сервер предоставит синтетический файл go.mod
, если у исходного модуля его не было.
+incompatible
(Несовместимые версии)
Модуль, выпущенный в основной версии 2
или выше, должен иметь соответствующий суффикс основной версии в своем пути модуля. Например, если модуль выпущен в версии v2.0.0
, его путь должен иметь суффикс /v2
. Это позволяет команде go
обрабатывать несколько основных версий проекта как отдельные модули, даже если они разработаны в одном репозитории.
Требование о суффиксе основной версии было введено, когда в команду go
была добавлена поддержка модулей, и многие репозитории уже имели теги с основной версией 2
или выше до этого. Для обеспечения совместимости с этими репозиториями команда go добавляет суффикс +incompatible
к версиям с основной версией 2
или выше без файла go.mod
. +incompatible
указывает, что версия является частью того же модуля, что и версии с более низкими номерами основных версий; следовательно, команда go
может автоматически обновлять до более высоких версий +incompatible
, даже если это может привести к сбою сборки.
Рассмотрим пример требования ниже:
require example.com/m v4.1.2+incompatible
Версия v4.1.2+incompatible
относится к семантическому тегу версии v4.1.2
в репозитории, который предоставляет модуль example.com/m
. Модуль должен находиться в корневом каталоге репозитория (то есть корневой путь репозитория также должен быть example.com/m
), и файл go.mod
не должен присутствовать. Модуль может иметь версии с более низкими номерами основных версий, такие как v1.5.2
, и команда go
может автоматически обновить их до v4.1.2+incompatible
(см. минимальный выбор версии (MVS
) для получения информации о том, как работают обновления).
Репозиторий, который переходит на модули после того, как версия v2.0.0
была помечена тегом, обычно должен выпустить новую основную версию. В приведенном выше примере автор должен создать модуль с путем example.com/m/v5
и выпустить версию v5.0.0
. Автор также должен обновить импорт пакетов в модуле, чтобы использовать префикс example.com/m/v5
вместо example.com/m
. Более подробный пример см. в разделе Go Modules: v2 and Beyond.
Обратите внимание, что суффикс +incompatible
не должен появляться в теге в репозитории; тег типа v4.1.2+incompatible
будет игнорироваться. Суффикс появляется только в версиях, используемых командой go
. Подробнее о различиях между версиями и тегами см. в разделе Сопоставление версий с коммитами.
Обратите внимание, что суффикс +incompatible
может появляться в псевдоверсиях. Например, v2.0.1-20200722182040-012345abcdef+incompatible
может быть действительной псевдоверсией.
Минимальная совместимость модулей
Модуль, выпущенный в основной версии 2
или выше, должен иметь суффикс основной версии в своем пути модуля. Модуль может быть разработан в подкаталоге основной версии в своем репозитории, а может и нет. Это имеет значение для пакетов, которые импортируют пакеты внутри модуля при сборке в режиме GOPATH
.
Обычно в режиме GOPATH
пакет хранится в каталоге, соответствующем корневому пути его репозитория, соединенному с его каталогом в репозитории. Например, пакет в репозитории с корневым путем example.com/repo
в подкаталоге sub
будет храниться в $GOPATH/src/example.com/repo/sub
и будет импортироваться как example.com/repo/sub
.
Для модуля с суффиксом основной версии можно ожидать, что пакет example.com/repo/v2/sub
будет находиться в каталоге $GOPATH/src/example.com/repo/v2/sub
. Для этого модуль должен быть разработан в подкаталоге v2
своего репозитория. Команда go
поддерживает это, но не требует (см. Сопоставление версий с коммитами).
Если модуль не разрабатывается в подкаталоге основной версии, то его каталог в GOPATH
не будет содержать суффикс основной версии, и его пакеты могут быть импортированы без суффикса основной версии. В приведенном выше примере пакет будет находиться в каталоге $GOPATH/src/example.com/repo/sub
и будет импортирован как example.com/repo/sub
.
Это создает проблему для пакетов, предназначенных для сборки как в режиме модуля, так и в режиме GOPATH
: режим модуля требует суффикса, а режим GOPATH
— нет.
Чтобы исправить это, в Go 1.11 была добавлена минимальная совместимость модулей, которая была обратно портирована в Go 1.9.7 и 1.10.3. Когда путь импорта разрешается в каталог в режиме GOPATH
:
-
При разрешении импорта в форме
$modpath/$vn/$dir
, где:$modpath
— действительный путь к модулю,$vn
— суффикс основной версии,$dir
— возможно пустой подкаталог,
-
Если выполняются все следующие условия:
- Пакет
$modpath/$vn/$dir
отсутствует в любом соответствующем каталоге поставщика. - Файл
go.mod
присутствует в том же каталоге, что и импортирующий файл, или в любом родительском каталоге до корня$GOPATH/src
. - Не существует каталога
$GOPATH[i]/src/$modpath/$vn/$suffix
(для любого корня$GOPATH[i]
), - Существует файл
$GOPATH[d]/src/$modpath/go.mod
(для некоторого корня$GOPATH[d]
), который объявляет путь к модулю как$modpath/$vn
,
- Пакет
-
Тогда импорт
$modpath/$vn/$dir
разрешается в каталог$GOPATH[d]/src/$modpath/$dir
.
Эти правила позволяют пакетам, которые были перенесены в модули, импортировать другие пакеты, которые были перенесены в модули при сборке в режиме GOPATH
, даже если не использовался подкаталог основной версии.
Команды с поддержкой модулей
Большинство команд go
могут работать в режиме с поддержкой модулей или в режиме GOPATH
. В режиме с поддержкой модулей команда go
использует файлы go.mod
для поиска версионных зависимостей и обычно загружает пакеты из кэша модулей, скачивая модули, если они отсутствуют. В режиме GOPATH
команда go
игнорирует модули; она ищет зависимости в каталогах поставщиков и в GOPATH
.
Начиная с Go 1.16, режим с поддержкой модулей включен по умолчанию, независимо от наличия файла go.mod
. В более ранних версиях режим с поддержкой модулей включался, если файл go.mod
присутствовал в текущем каталоге или любом родительском каталоге.
Режим с поддержкой модулей можно контролировать с помощью переменной среды GO111MODULE
, которую можно установить в значение on
, off
или auto
.
- Если
GO111MODULE=off
, командаgo
игнорирует файлыgo.mod
и работает в режимеGOPATH
. - Если
GO111MODULE=on
или не установлено, командаgo
работает в режиме распознавания модулей, даже если файлgo.mod
отсутствует. Не все команды работают без файлаgo.mod
: см. Команды модулей вне модуля. - Если
GO111MODULE=auto
, командаgo
работает в режиме с поддержкой модулей, если файлgo.mod
присутствует в текущем каталоге или любом родительском каталоге. В Go 1.15 и ниже это было поведением по умолчанию. Подкомандыgo mod
иgo install
с запросом версии работают в режиме с поддержкой модулей, даже если файлgo.mod
отсутствует.
В режиме распознавания модулей GOPATH больше не определяет значение импортов во время сборки, но по-прежнему хранит загруженные зависимости (в GOPATH/pkg/mod
; см. Кэш модулей) и установленные команды (в GOPATH/bin
, если не установлен GOBIN
).
(builds
) Команды сборки
Все команды, которые загружают информацию о пакетах, учитывают модули. К ним относятся:
go build
go fix
go generate
go install
go list
go run
go test
go vet
При запуске в режиме распознавания модулей эти команды используют файлы go.mod
для интерпретации путей импорта, указанных в командной строке или записанных в исходных файлах Go. Эти команды принимают следующие флаги, общие для всех команд модулей.
- Флаг
-mod
контролирует, может лиgo.mod
обновляться автоматически и используется ли каталогvendor
.-mod=mod
указывает командеgo
игнорировать каталог vendor и автоматически обновлятьgo.mod
, например, когда импортируемый пакет не предоставляется ни одним из известных модулей.-mod=readonly
указывает командеgo
игнорировать каталогvendor
и сообщать об ошибке, еслиgo.mod
необходимо обновить.-mod=vendor
указывает командеgo
использовать каталогvendor
. В этом режиме командаgo
не будет использовать сеть или кэш модулей.- По умолчанию, если версия
go
вgo.mod
равна 1.14 или выше и присутствует каталогvendor
, командаgo
действует так, как если бы был использован флаг-mod=vendor
. В противном случае командаgo
действует так, как если бы был использован флаг-mod=readonly
. go get
отклоняет этот флаг, поскольку цель команды — изменить зависимости, что разрешено только с помощью-mod=mod
.
- Флаг
-modcacherw
указывает командеgo
создавать новые каталоги в кэше модулей с правами на чтение и запись, а не делать их доступными только для чтения. При постоянном использовании этого флага (обычно путем установкиGOFLAGS=-modcacherw
в среде или запускаgo env -w GOFLAGS=-modcacherw
) кэш модулей можно удалить с помощью таких команд, какrm -r
, без предварительного изменения прав доступа. Командаgo clean -modcache
может использоваться для удаления кэша модулей, независимо от того, использовался ли флаг-modcacherw
. - Флаг
-modfile=file.mod
указывает командеgo
читать (и, возможно, записывать) альтернативный файл вместоgo.mod
в корневом каталоге модулей. Имя файла должно заканчиваться на.mod
. Файл с именемgo.mod
по-прежнему должен присутствовать, чтобы определить корневой каталог модулей, но доступ к нему не осуществляется. Когда указан-modfile
, также используется альтернативный файлgo.sum
: его путь получается из флага-modfile
путем удаления расширения.mod
и добавления.sum
.
Vendoring
При использовании модулей команда go
обычно удовлетворяет зависимости, загружая модули из их источников в кэш модулей, а затем загружая пакеты из этих загруженных копий. Vendoring
может использоваться для обеспечения взаимодействия со старыми версиями Go или для обеспечения хранения всех файлов, используемых для сборки, в одном дереве файлов.
Команда go mod vendor
создает каталог с именем vendor
в корневом каталоге главного модуля, содержащий копии всех пакетов, необходимых для сборки и тестирования пакетов в главном модуле. Пакеты, которые импортируются только тестами пакетов вне главного модуля, не включаются. Как и в случае с go mod tidy
и другими командами модулей, ограничения сборки, за исключением ignore
, не учитываются при создании каталога vendor
.
go mod vendor
также создает файл vendor/modules.txt
, который содержит список пакетов vendor
и версии модулей, из которых они были скопированы. Когда vendoring
включен, этот манифест используется в качестве источника информации о версии модуля, как сообщается go list -m
и go version -m
. Когда команда go
читает vendor/modules.txt
, она проверяет, что версии модулей соответствуют go.mod
. Если go.mod
изменился с момента создания vendor/modules.txt
, команда go
сообщит об ошибке. go mod vendor
следует запустить снова, чтобы обновить каталог vendor
.
Если каталог vendor
присутствует в корневом каталоге основного модуля, он будет использоваться автоматически, если версия go
в файле go.mod
основного модуля равна 1.14 или выше. Чтобы явно включить vendoring
, вызовите команду go
с флагом -mod=vendor
. Чтобы отключить vendoring
, используйте флаг -mod=readonly
или -mod=mod
.
Когда vendoring
включен, команды сборки, такие как go build
и go test
, загружают пакеты из каталога vendor
вместо доступа к сети или локальному кэшу модулей. Команда go list -m
выводит только информацию о модулях, перечисленных в go.mod
. Команды go mod
, такие как go mod download
и go mod tidy
, не работают по-другому, когда vendoring
включен, и по-прежнему загружают модули и обращаются к кэшу модулей. go get
также не работает по-другому, когда vendoring
включен.
В отличие от вендоринга в режиме GOPATH
, команда go
игнорирует каталоги vendor
, расположенные не в корневом каталоге основного модуля. Кроме того, поскольку каталоги vendor
в других модулях не используются, команда go
не включает каталоги vendor при сборке zip-файлов модулей (но см. известные ошибки #31562 и #37397).
go get
Использование:
go get [-d] [-t] [-u] [build flags] [packages]
Примеры:
# Upgrade a specific module.
$ go get golang.org/x/net
# Upgrade modules that provide packages imported by packages in the main module.
$ go get -u ./...
# Upgrade or downgrade to a specific version of a module.
$ go get golang.org/x/text@v0.3.2
# Update to the commit on the module's master branch.
$ go get golang.org/x/text@master
# Remove a dependency on a module and downgrade modules that require it
# to versions that don't require it.
$ go get golang.org/x/text@none
# Upgrade the minimum required Go version for the main module.
$ go get go
# Upgrade the suggested Go toolchain, leaving the minimum Go version alone.
$ go get toolchain
# Upgrade to the latest patch release of the suggested Go toolchain.
$ go get toolchain@patch
Команда go get
обновляет зависимости модулей в файле go.mod
для основного модуля, а затем собирает и устанавливает пакеты, указанные в командной строке.
Первый шаг — определить, какие модули необходимо обновить.
go get
принимает в качестве аргументов список пакетов, шаблоны пакетов и пути к модулям.- Если указан аргумент пакета,
go get
обновляет модуль, который предоставляет этот пакет. - Если указан шаблон пакета (например,
all
или путь с подстановочным символом …),go get
расширяет шаблон до набора пакетов, а затем обновляет модули, которые предоставляют эти пакеты. - Если аргумент указывает модуль, но не пакет (например, модуль
golang.org/x/net
не имеет пакета в своем корневом каталоге),go get
обновит модуль, но не скомпилирует пакет. - Если аргументы не указаны,
go get
действует так, как если бы был указан (пакет в текущем каталоге); это можно использовать вместе с флагом-u
для обновления модулей, которые предоставляют импортированные пакеты.
Каждый аргумент может включать суффикс запроса версии, указывающий желаемую версию, как в go get golang.org/x/text@v0.3.0
. Суффикс запроса версии состоит из символа @
, за которым следует запрос версии, который может указывать конкретную версию (v0.3.0
), префикс версии (v0.3
), имя ветки или тега (master
), ревизию (1234abcd
) или один из специальных запросов latest
, upgrade
, patch
или none
. Если версия не указана, go get
использует запрос @upgrade
.
После того как go get
разрешит свои аргументы для конкретных модулей и версий, go get
добавит, изменит или удалит директивы require
в файле go.mod
основного модуля, чтобы обеспечить сохранение модулей в желаемых версиях в будущем. Обратите внимание, что требуемые версии в файлах go.mod
являются минимальными версиями и могут быть автоматически увеличены при добавлении новых зависимостей. См. раздел «Выбор минимальной версии (MVS
)» для получения подробной информации о том, как версии выбираются и конфликты разрешаются командами, учитывающими модули.
Другие модули могут быть обновлены, когда модуль, указанный в командной строке, добавляется, обновляется или понижается, если новая версия указанного модуля требует другие модули более высоких версий. Например, предположим, что модуль example.com/a
обновлен до версии v1.5.0
, и эта версия требует модуль example.com/b
версии v1.2.0
. Если в настоящее время требуется модуль example.com/b
версии v1.1.0
, то go get example.com/a@v1.5.0
также обновит example.com/b
до v1.2.0
.
Другие модули могут быть понижены, когда модуль, названный в командной строке, понижается или удаляется. Продолжая приведенный выше пример, предположим, что модуль example.com/b
понижен до версии v1.1.0
. Модуль example.com/a
также будет понижен до версии, которая требует example.com/b
версии v1.1.0
или ниже.
Требование модуля может быть удалено с помощью суффикса версии @none
. Это особый вид понижения версии. Модули, которые зависят от удаленного модуля, будут понижены или удалены по мере необходимости. Требование модуля может быть удалено, даже если один или несколько его пакетов импортируются пакетами в основном модуле. В этом случае следующая команда сборки может добавить новое требование модуля.
Если модуль требуется в двух разных версиях (явно указанных в аргументах командной строки или для удовлетворения требований обновлений и понижений версии), go get
выдаст ошибку.
После того, как go get
выбрал новый набор версий, он проверяет, не были ли отозваны или не стали ли устаревшими какие-либо вновь выбранные версии модулей или какие-либо модули, предоставляющие пакеты, указанные в командной строке. go get
выводит предупреждение для каждой найденной отозванной версии или устаревшего модуля. go list -m -u all
можно использовать для проверки отзывов и устаревания во всех зависимостях.
После обновления файла go.mod
go get
собирает пакеты, указанные в командной строке. Исполняемые файлы будут установлены в каталог, указанный переменной окружения GOBIN
, которая по умолчанию равна $GOPATH/bin
или $HOME/go/bin
, если переменная окружения GOPATH
не установлена.
go get
поддерживает следующие флаги:
- Флаг
-d
указываетgo get
не собирать и не устанавливать пакеты. При использовании-d
go get
будет только управлять зависимостями вgo.mod
. Использованиеgo
get без-d
для сборки и установки пакетов является устаревшим (начиная с Go 1.17). В Go 1.18-d
будет всегда включен. - Флаг
-u
указываетgo get
обновить модули, предоставляющие пакеты, импортируемые прямо или косвенно пакетами, указанными в командной строке. Каждый модуль, выбранный с помощью-u
, будет обновлен до последней версии, если он уже не требуется в более поздней версии (предварительная версия). - Флаг
-u=patch
(не-u patch
) также указываетgo get
обновить зависимости, ноgo get
обновит каждую зависимость до последней патч-версии (аналогично запросу версии@patch
). - Флаг
-t
указываетgo get
учитывать модули, необходимые для сборки тестов пакетов, указанных в командной строке. При совместном использовании-t
и-u
go get
также обновит тестовые зависимости. - Флаг
-insecure
больше не следует использовать. Он позволяетgo get
разрешать пользовательские пути импорта и загружать из репозиториев и прокси-серверов модулей, используя небезопасные схемы, такие какHTTP
. Переменная средыGOINSECURE
обеспечивает более тонкий контроль и должна использоваться вместо него.
go get
больше ориентирован на управление требованиями в go.mod
. Флаг -d
является устаревшим, и в Go 1.18 он будет всегда включен.
go install
Начиная с Go 1.16,
go install
является рекомендуемой командой для сборки и установки программ. При использовании с суффиксом версии (например,@latest
или@v1.4.6
)go install
собирает пакеты в режиме с учетом модулей, игнорируя файлgo.mod
в текущем каталоге или любом родительском каталоге, если таковой имеется.
Использование:
go install [build flags] [packages]
Примеры:
# Install the latest version of a program,
# ignoring go.mod in the current directory (if any).
$ go install golang.org/x/tools/gopls@latest
# Install a specific version of a program.
$ go install golang.org/x/tools/gopls@v0.6.4
# Install a program at the version selected by the module in the current directory.
$ go install golang.org/x/tools/gopls
# Install all programs in a directory.
$ go install ./cmd/...
Команда go install
собирает и устанавливает пакеты, указанные в командной строке. Исполняемые файлы (основные пакеты) устанавливаются в каталог, указанный переменной среды GOBIN
, которая по умолчанию равна $GOPATH/bin
или $HOME/go/bin
, если переменная среды GOPATH
не задана. Исполняемые файлы в $GOROOT
устанавливаются в $GOROOT/bin
или $GOTOOLDIR
вместо $GOBIN
. Неисполняемые пакеты собираются и кэшируются, но не устанавливаются.
Начиная с Go 1.16, если аргументы имеют суффиксы версии (такие как @latest
или @v1.0.0
), go install
собирает пакеты в режиме с учетом модулей, игнорируя файл go.mod
в текущем каталоге или любом родительском каталоге, если таковой имеется. Это полезно для установки исполняемых файлов без влияния на зависимости основного модуля.
Чтобы устранить неоднозначность в отношении того, какие версии модулей используются в сборке, аргументы должны удовлетворять следующим ограничениям:
- Аргументы должны быть путями к пакетам или шаблонами пакетов (с подстановочными знаками
«...»
). Они не должны быть стандартными пакетами (такими какfmt)
, меташаблонами (std
,cmd
,all
,work
,tool
) или относительными или абсолютными путями к файлам. - Все аргументы должны иметь одинаковый суффикс версии. Различные запросы не допускаются, даже если они относятся к одной и той же версии.
- Все аргументы должны относиться к пакетам в одном и том же модуле с одной и той же версией.
- Аргументы пути к пакету должны относиться к основным пакетам. Аргументы шаблона будут соответствовать только основным пакетам.
- Ни один модуль не считается основным модулем.
- Если модуль, содержащий пакеты, указанные в командной строке, имеет файл
go.mod
, он не должен содержать директивы (replace
иexclude)
, которые привели бы к его интерпретации по-другому, если бы он был основным модулем. - Модуль не должен требовать более высокой версии самого себя.
- Каталоги поставщиков не используются ни в одном модуле. (Каталоги поставщиков не включаются в zip-файлы модулей, поэтому
go install
не загружает их).
- Если модуль, содержащий пакеты, указанные в командной строке, имеет файл
См. Запросы версии для поддерживаемого синтаксиса запросов версии. Go 1.15 и ниже не поддерживали использование запросов версии с go install
.
Если аргументы не имеют суффиксов версии, go install
может работать в режиме с поддержкой модулей или в режиме GOPATH
, в зависимости от переменной среды GO111MODULE
и наличия файла go.mod
. Подробности см. в разделе Команды с поддержкой модулей. Если режим с поддержкой модулей включен, go install
работает в контексте основного модуля, который может отличаться от модуля, содержащего устанавливаемый пакет.
go list -m
Использование:
go list -m [-u] [-retracted] [-versions] [list flags] [modules]
Примеры:
$ go list -m all
$ go list -m -versions example.com/m
$ go list -m -json example.com/m@latest
Флаг -m
заставляет go list
перечислять модули, а не пакеты. В этом режиме аргументами go list
могут быть модули, шаблоны модулей (содержащие подстановочный знак ...
), запросы версий или специальный шаблон all
, который соответствует всем модулям в списке сборки. Если аргументы не указаны, то в списке будет указан главный модуль.
При перечислении модулей флаг -f
по-прежнему задает шаблон формата, применяемый к структуре Go, но теперь уже к структуре Module:
type Module struct {
Path string // путь к модулю
Version string // версия модуля
Versions []string // доступные версии модуля
Replace *Module // заменяется этим модулем
Time *time.Time // время создания версии
Update *Module // доступное обновление (с -u)
Main bool // является ли это главным модулем?
Indirect bool // модуль требуется основному модулю только косвенно
Dir string // каталог, содержащий локальную копию файлов, если таковая имеется
GoMod string // путь к файлу go.mod, описывающему модуль, если таковой имеется
GoVersion string // версия go, используемая в модуле
Retracted []string // информация об отзыве, если таковая имеется (с -retracted или -u)
Deprecated string // сообщение об устаревании, если есть (с -u)
Error *ModuleError // ошибка при загрузке модуля
}
type ModuleError struct {
Err string // сама ошибка
}
По умолчанию выводится путь к модулю, а затем информация о версии и замене, если таковая имеется. Например, go list -m all
может вывести:
example.com/main/module
golang.org/x/net v0.1.0
golang.org/x/text v0.3.0 => /tmp/text
rsc.io/pdf v0.1.1
В структуре Module
есть метод String
, который форматирует эту строку вывода, так что формат по умолчанию эквивалентен -f '{{.String}}'
.
Обратите внимание, что если модуль был заменен, его поле Replace
описывает заменяющий модуль, а его поле Dir
устанавливается в исходный код заменяющего модуля, если он присутствует. (То есть, если Replace
не имеет значения nil
, то Dir
устанавливается в Replace.Dir
, без доступа к исходному коду замененного модуля).
Флаг -u
добавляет информацию о доступных обновлениях. Если последняя версия данного модуля новее текущей, list -u
устанавливает в поле Update
модуля информацию о более новом модуле.
list -u
также выводит, является ли выбранная в данный момент версия отмененной и является ли модуль устаревшим. Метод String
модуля указывает на доступное обновление путем форматирования новой версии в скобках после текущей версии.
Например,
go list -m -u all
может вывести:
example.com/main/module
golang.org/x/old v1.9.9 (deprecated)
golang.org/x/net v0.1.0 (retracted) [v0.2.0]
golang.org/x/text v0.3.0 [v0.4.0] => /tmp/text
rsc.io/pdf v0.1.1 [v0.1.2]
(Для инструментов может быть удобнее использовать команду go list -m -u -json all
для анализа.)
Флаг -versions
заставляет list
установить поле Versions
модуля в список всех известных версий этого модуля, упорядоченных в соответствии с семантической версией, от самой низкой к самой высокой. Флаг также изменяет формат вывода по умолчанию, чтобы отобразить путь к модулю, за которым следует список версий, разделенных пробелами. Отмененные версии опускаются из этого списка, если не указан флаг -retracted
.
Флаг -retracted
указывает list
показывать отозванные версии в списке, выведенном с помощью флага -versions
, и учитывать отозванные версии при разрешении запросов версий.
Например,
go list -m -retracted example.com/m@latest
показывает самую последнюю версию или предрелизную версию модуляexample.com/m
, даже если эта версия отозвана. Директивыretract
иdeprecations
загружаются из файлаgo.mod
в этой версии. Флаг-retracted
был добавлен в Go 1.16.
Шаблонная функция module
принимает один строковый аргумент, который должен быть путем к модулю или запросом, и возвращает указанный модуль в виде структуры Module
. Если происходит ошибка, результатом будет структура Module
с полем Error
, не равным nil
.
go mod download
Использование:
go mod download [-x] [-json] [-reuse=old.json] [modules]
Например:
$ go mod download
$ go mod download golang.org/x/mod@v0.2.0
Команда go mod download
загружает именованные модули в кэш модулей. Аргументами могут быть пути к модулям или шаблоны модулей, выбирающие зависимости основного модуля, или запросы версий вида path@version
. При отсутствии аргументов загрузка применяется ко всем зависимостям основного модуля.
Команда go
будет автоматически загружать модули по мере необходимости во время обычного выполнения. Команда go mod download
полезна в основном для предварительного заполнения кэша модулей или для загрузки данных, которые будут обслуживаться прокси-модулем.
По умолчанию команда загрузки ничего не пишет в стандартный вывод. Она печатает сообщения о ходе выполнения и ошибках в стандартную ошибку.
Флаг -json
заставляет команду download
выводить на стандартный вывод последовательность JSON-объектов, описывающих каждый загруженный модуль (или сбой), соответствующий данной Go-структуре:
type Module struct {
Path string // module path
Query string // version query corresponding to this version
Version string // module version
Error string // error loading module
Info string // absolute path to cached .info file
GoMod string // absolute path to cached .mod file
Zip string // absolute path to cached .zip file
Dir string // absolute path to cached source root directory
Sum string // checksum for path, version (as in go.sum)
GoModSum string // checksum for go.mod (as in go.sum)
Origin any // provenance of module
Reuse bool // reuse of old module info is safe
}
Флаг -x
заставляет download
выводить команды, выполняемые download
, в стандартную ошибку.
Флаг -reuse
принимает имя файла, содержащего JSON-вывод предыдущего вызова ‘go mod download -json
’. Команда go
может использовать этот файл, чтобы определить, что модуль не изменился с момента предыдущего вызова, и избежать его повторной загрузки. Модули, которые не будут перезагружены, будут отмечены в новом выводе установкой поля Reuse
в true
. Обычно кэш модулей обеспечивает такое повторное использование автоматически; флаг -reuse
может быть полезен в системах, не сохраняющих кэш модулей.
go mod edit
Использование:
go mod edit [editing flags] [-fmt|-print|-json] [go.mod]
Например:
# Add a replace directive.
$ go mod edit -replace example.com/a@v1.0.0=./a
# Remove a replace directive.
$ go mod edit -dropreplace example.com/a@v1.0.0
# Set the go version, add a requirement, and print the file
# instead of writing it to disk.
$ go mod edit -go=1.14 -require=example.com/m@v1.0.0 -print
# Format the go.mod file.
$ go mod edit -fmt
# Format and print a different .mod file.
$ go mod edit -print tools.mod
# Print a JSON representation of the go.mod file.
$ go mod edit -json
Команда go mod edit
предоставляет интерфейс командной строки для редактирования и форматирования файлов go.mod
, предназначенный в первую очередь для использования инструментами и скриптами. go mod edit
читает только один файл go.mod
; он не ищет информацию о других модулях. По умолчанию go mod edit
читает и записывает файл go.mod
основного модуля, но после флагов редактирования можно указать другой целевой файл.
Флаги редактирования определяют последовательность операций редактирования.
- Флаг
-module
изменяет путь модуля (строку модуля в файлеgo.mod
). - Флаг
-go=version
устанавливает ожидаемую версию языка Go. - Флаги
-require=path@version
и-droprequire=path
добавляют и удаляют требование к указанному пути и версии модуля. Обратите внимание, что-require
переопределяет все существующие требования к пути. Эти флаги в основном предназначены для инструментов, которые понимают граф модулей. Пользователям следует отдавать предпочтениеgo get path@version
илиgo get path@none
, которые производят другие настройкиgo.mod
по мере необходимости, чтобы удовлетворить ограничения, налагаемые другими модулями. См.go get
. - Флаги
-exclude=path@version
и-dropexclude=path@version
добавляют и удаляют исключение для указанного пути модуля и версии. Обратите внимание, что-exclude=path@version
не выполняется, если такое исключение уже существует. - Флаг
-replace=old[@v]=new[@v]
добавляет замену указанной пары пути модуля и версии. Если@v
вold@v
опущено, добавляется замена без версии в левой части, которая применяется ко всем версиям старого пути модуля. Если@v
вnew@v
опущено, новый путь должен быть локальным корневым каталогом модуля, а не путем модуля. Обратите внимание, что-replace
переопределяет любые избыточные замены дляold[@v]
, поэтому опущение@v
удалит замены для определенных версий. - Флаг
-dropreplace=old[@v]
отменяет замену заданного пути модуля и пары версий. Если@v
указан, то отменяется замена с заданной версией. Существующая замена без версии в левой части может по-прежнему заменять модуль. Если@v
опущен, то отменяется замена без версии. - Флаги
-retract=version
и-dropretract=version
добавляют и удаляют отзыв для заданной версии, которая может быть одной версией (например,v1.2.3
) или интервалом (например,[v1.1.0,v1.2.0]
). Обратите внимание, что флаг-retract
не может добавлять комментарий с обоснованием для директивы отзыва. Комментарии с обоснованием рекомендуются и могут отображаться с помощьюgo list -m -u
и других команд. - Флаги
-tool=path
и-droptool=path
добавляют и удаляют директивуtool
для указанных путей. Обратите внимание, что это не добавит необходимые зависимости в граф сборки. Пользователям рекомендуется использоватьgo get -tool path
для добавления инструмента илиgo get -tool path@none
для его удаления.
Флаги редактирования могут повторяться. Изменения применяются в указанном порядке.
go mod edit
имеет дополнительные флаги, которые контролируют его вывод.
- Флаг
-fmt
переформатирует файлgo.mod
без внесения других изменений. Это переформатирование также подразумевается любыми другими изменениями, которые используют или переписывают файлgo.mod
. Этот флаг нужен только в том случае, если не указаны другие флаги, как вgo mod edit -fmt
. - Флаг
-print
выводит окончательный файлgo.mod
в текстовом формате вместо записи обратно на диск. - Флаг
-json
выводит окончательный файлgo.mod
в формате JSON вместо записи обратно на диск в текстовом формате. Вывод JSON соответствует следующим типам Go:
type Module struct {
Path string
Version string
}
type GoMod struct {
Module ModPath
Go string
Require []Require
Exclude []Module
Replace []Replace
Retract []Retract
}
type ModPath struct {
Path string
Deprecated string
}
type Require struct {
Path string
Version string
Indirect bool
}
type Replace struct {
Old Module
New Module
}
type Retract struct {
Low string
High string
Rationale string
}
type Tool struct {
Path string
}
Обратите внимание, что здесь описывается только сам файл go.mod
, а не другие модули, на которые есть косвенные ссылки. Для получения полного набора модулей, доступных для сборки, используйте go list -m -json all
. См. go list -m
.
Например, инструмент может получить файл
go.mod
в виде структуры данных, разобрав выводgo mod edit -json
, а затем внести изменения, вызвавgo mod edit
с параметрами-require
,-exclude
и так далее.
Инструменты также могут использовать пакет golang.org/x/mod/modfile
для разбора, редактирования и форматирования файлов go.mod
.
go mod graph
Использование:
go mod graph [-go=version]
Команда go mod graph выводит граф требований к модулю (с примененными заменами) в текстовом виде.
Например:
example.com/main example.com/a@v1.1.0
example.com/main example.com/b@v1.2.0
example.com/a@v1.1.0 example.com/b@v1.1.1
example.com/a@v1.1.0 example.com/c@v1.3.0
example.com/b@v1.1.0 example.com/c@v1.1.0
example.com/b@v1.2.0 example.com/c@v1.2.0
Каждая вершина в графе модуля представляет собой определенную версию модуля. Каждое ребро в графе представляет собой требование к минимальной версии зависимости.
go mod graph
выводит ребра графа по одному в строке. Каждая строка содержит два поля, разделенных пробелами: версию модуля и одну из его зависимостей. Каждая версия модуля идентифицируется как строка вида path@version
. Главный модуль не имеет суффикса @version
, так как у него нет версии.
Флаг -go
заставляет go mod graph
сообщать о том, что граф модуля загружен данной версией Go, а не версией, указанной директивой go
в файле go.mod
.
Дополнительные сведения о том, как выбираются версии, см. в разделе Минимальный выбор версии (MVS
). См. также go list -m
для печати выбранных версий и go mod why
для понимания того, зачем нужен тот или иной модуль.
go mod init
Использование:
go mod init [module-path]
Пример:
go mod init
go mod init example.com/m
Команда go mod init
инициализирует и записывает новый файл go.mod
в текущем каталоге, фактически создавая новый модуль, укорененный в текущем каталоге. Файл go.mod
не должен уже существовать.
init
принимает один необязательный аргумент - путь к модулю для нового модуля. Инструкции по выбору пути к модулю см. в разделе Пути к модулю. Если аргумент путь к модулю опущен, init
попытается определить путь к модулю, используя комментарии импорта в файлах .go
и текущий каталог (если он есть в GOPATH
).
go mod tidy
Использование:
go mod tidy [-e] [-v] [-x] [-diff] [-go=версия] [-compat=версия]
go mod tidy
обеспечивает соответствие файла go.mod
исходному коду в модуле. Он добавляет все недостающие требования к модулям, необходимые для сборки пакетов и зависимостей текущего модуля, и удаляет требования к модулям, которые не предоставляют никаких соответствующих пакетов. Он также добавляет все недостающие записи в go.sum
и удаляет ненужные записи.
- Флаг
-e
(добавлен в Go 1.16) заставляетgo mod tidy
пытаться продолжить работу, несмотря на ошибки, возникшие при загрузке пакетов. - Флаг
-v
заставляетgo mod tidy
выводить информацию об удаленных модулях в стандартный вывод ошибок. - Флаг
-x
заставляетgo mod tidy
выводить команды, которые выполняетtidy
. - Флаг
-diff
заставляетgo mod tidy
не изменятьgo.mod
илиgo.sum
, а вместо этого выводить необходимые изменения в виде унифицированногоdiff
. Он завершается с кодом, отличным от нуля, еслиdiff
не пустой.
go mod tidy
работает, загружая все пакеты в основном модуле, все его инструменты и все пакеты, которые они импортируют, рекурсивно. Сюда входят пакеты, импортированные тестами (включая тесты в других модулях).
go mod tidy
действует так, как если бы все теги сборки были включены, поэтому он будет учитывать платформозависимые исходные файлы и файлы, которые требуют настраиваемых тегов сборки, даже если эти исходные файлы обычно не собираются.
Есть одно исключение: тег сборки ignore
не включен, поэтому файл с ограничением сборки // +build ignore
не будет учитываться.
Обратите внимание, что go mod tidy
не будет учитывать пакеты в главном модуле в каталогах с именем testdata
или с именами, начинающимися с .
или _
, если эти пакеты явно не импортируются другими пакетами.
После загрузки этого набора пакетов go mod tidy
убеждается, что каждый модуль, предоставляющий один или несколько пакетов, имеет директиву require
в файле go.mod
основного модуля или — если основной модуль находится на go 1.16
или ниже — требуется другим необходимым модулем.
go mod tidy
добавит требование к последней версии каждого отсутствующего модуля (определение последней версии см. в разделе «Запросы версии»).go mod tidy
удалит директивы require для модулей, которые не предоставляют никаких пакетов в описанном выше наборе.go mod tidy
также может добавлять или удалять// косвенные комментарии
к директивамrequire
.
// Косвенный комментарий
обозначает модуль, который не предоставляет пакет, импортируемый пакетом в основном модуле. (См. директиву require
для получения более подробной информации о том, когда добавляются // косвенные зависимости
и комментарии
).
Если установлен флаг -go
, go mod tidy
обновит директиву go
до указанной версии, включив или отключив обрезку графа модулей и отложенную загрузку модулей (а также добавив или удалив косвенные требования по мере необходимости) в соответствии с этой версией.
По умолчанию go mod tidy
проверяет, что выбранные версии модулей не изменяются при загрузке графа модулей версией Go, непосредственно предшествующей версии, указанной в директиве go
. Версию, проверяемую на совместимость, также можно явно указать с помощью флага -compat
.
go mod vendor
Использование:
go mod vendor [-e] [-v] [-o]
Команда go mod vendor
создает в корневом каталоге основного модуля каталог с именем vendor
, который содержит копии всех пакетов, необходимых для поддержки сборки и тестирования пакетов в основном модуле. Пакеты, которые импортируются только тестами пакетов вне основного модуля, не включаются. Как и в случае с go mod tidy
и другими командами модуля, при создании каталога vendor
не учитываются ограничения сборки, за исключением ignore
.
Когда vendoring
включен, команда go
загружает пакеты из каталога vendor
вместо того, чтобы загружать модули из их источников в кэш модулей и использовать пакеты из этих загруженных копий. Дополнительную информацию см. в разделе Vendoring
.
go mod vendor
также создает файл vendor/modules.txt
, который содержит список пакетов vendored
и версии модулей, из которых они были скопированы.
Когда vendoring
включен, этот манифест используется в качестве источника информации о версии модуля, как сообщается go list -m
и go version -m
. Когда команда go
читает vendor/modules.txt
, она проверяет, что версии модулей соответствуют go.mod
.
Если go.mod
изменился с момента создания vendor/modules.txt
, go mod vendor
следует запустить снова.
Обратите внимание, что go mod vendor
удаляет каталог vendor
, если он существует, перед его повторным созданием. Не следует вносить локальные изменения в пакеты, включенные в vendor
. Команда go
не проверяет, не были ли изменены пакеты в каталоге vendor
, но можно проверить целостность каталога vendor
, запустив go mod vendor
и убедившись, что никаких изменений не было.
- Флаг
-e
(добавлен в Go 1.16) заставляетgo mod vendor
пытаться продолжить работу, несмотря на ошибки, возникшие при загрузке пакетов. - Флаг
-v
заставляетgo mod vendor
выводить имена модулей и пакетов vendor в стандартный поток ошибок. - Флаг
-o
(добавлен в Go 1.18) заставляетgo mod vendor
выводить деревоvendor
в указанном каталоге вместоvendor
. Аргументом может быть либо абсолютный путь, либо путь относительно корня модуля.
go mod verify
Использование:
go mod verify
go mod verify
проверяет, что зависимости основного модуля, хранящиеся в кэше модулей, не были изменены с момента их загрузки.
Для выполнения этой проверки go mod verify
хеширует каждый загруженный файл .zip
модуля и извлеченный каталог, а затем сравнивает эти хеши с хешем, записанным при первой загрузке модуля.
go mod verify
проверяет каждый модуль в списке сборки (который можно вывести с помощью go list -m all
).
Если все модули не изменены, go mod verify
выводит сообщение «all modules verified»
(все модули проверены). В противном случае он сообщает, какие модули были изменены, и завершает работу с ненулевым статусом.
Обратите внимание, что все команды, поддерживающие модули, проверяют, что хэши в файле go.sum
основного модуля совпадают с хэшами, записанными для модулей, загруженных в кэш модулей. Если хеш отсутствует в go.sum
(например, потому что модуль используется впервые), команда go
проверяет его хеш с помощью базы данных контрольных сумм (если путь к модулю не соответствует GOPRIVATE
или GONOSUMDB
). Подробности см. в разделе Аутентификация модулей.
В отличие от этого, go mod verify
проверяет, что файлы .zip
модулей и их извлеченные каталоги имеют хеши, которые соответствуют хешам, записанным в кэше модулей при их первоначальной загрузке.
Это полезно для обнаружения изменений в файлах в кэше модулей после загрузки и проверки модуля.
go mod verify
не загружает содержимое для модулей, которые нет в кэше, и не использует файлы go.sum
для проверки содержимого модулей. Однако go mod verify
может загружать файлы go.mod
для выполнения минимального выбора версии. Он будет использовать go.sum
для проверки этих файлов и может добавлять записи go.sum
для отсутствующих хэшей.
go mod why
Использование:
go mod why [-m] [-vendor] packages...
go mod why
показывает кратчайший путь в графе импорта от главного модуля до каждого из перечисленных пакетов.
Вывод представляет собой последовательность строк, по одной для каждого пакета или модуля, указанного в командной строке, разделенных пустыми строками. Каждая строка начинается с комментария, начинающегося с #
, в котором указан целевой пакет или модуль.
Последующие строки содержат путь через граф импорта, по одному пакету в строке. Если пакет или модуль не упоминается в основном модуле, в строке будет отображаться одно примечание в скобках, указывающее на этот факт.
Например:
$ go mod why golang.org/x/text/language golang.org/x/text/encoding
# golang.org/x/text/language
rsc.io/quote
rsc.io/sampler
golang.org/x/text/language
# golang.org/x/text/encoding
(главный модуль не нуждается в пакете golang.org/x/text/encoding)
-
Флаг
-m
заставляетgo mod why
обрабатывать свои аргументы как список модулей.go mod why
выведет путь к любому пакету в каждом из модулей. Обратите внимание, что даже при использовании-m
go mod why
запрашивает граф пакетов, а не граф модулей, выведенныйgo mod graph
. -
Флаг
-vendor
заставляетgo mod why
игнорировать импорты в тестах пакетов вне основного модуля (как это делаетgo mod vendor
). По умолчаниюgo mod why
рассматривает граф пакетов, соответствующих шаблонуall
. Этот флаг не имеет эффекта после Go 1.16 в модулях, которые объявляютgo 1.16
или выше (используя директивуgo
вgo.mod
), поскольку значениеall
изменилось, чтобы соответствовать набору пакетов, соответствующихgo mod vendor
.
go version -m
Использование:
go version [-m] [-v] [файл ...]
Пример:
# Вывести версию Go, использованную для сборки go.
$ go version
# Вывести версию Go, использованную для сборки конкретного исполняемого файла.
$ go version ~/go/bin/gopls
# Вывести версию Go и версии модулей, использованные для сборки конкретного исполняемого файла.
$ go version -m ~/go/bin/gopls
# Вывести версию Go и версии модулей, использованные для сборки исполняемых файлов в каталоге.
$ go version -m ~/go/bin/
go version сообщает версию Go, использованную для сборки каждого исполняемого файла, указанного в командной строке.
Если в командной строке не указаны файлы, go version
выводит информацию о своей версии.
Если указан каталог, go version
рекурсивно просматривает этот каталог, ищет распознаваемые бинарные файлы Go и сообщает их версии.
По умолчанию go version
не сообщает о нераспознанных файлах, найденных во время сканирования каталога.
- Флаг
-v
заставляет его сообщать о нераспознанных файлах. - Флаг
-m
заставляетgo version
выводить информацию о версии встроенного модуля каждого исполняемого файла, если она доступна. Для каждого исполняемого файлаgo version -m
выводит таблицу с разделёнными табуляцией столбцами, как показано ниже.
$ go version -m ~/go/bin/goimports
/home/jrgopher/go/bin/goimports: go1.14.3
path golang.org/x/tools/cmd/goimports
mod golang.org/x/tools v0.0.0-20200518203908-8018eb2c26ba h1:0Lcy64USfQQL6GAJma8BdHCgeofcchQj+Z7j0SXYAzU=
dep golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
dep golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
Формат таблицы может измениться в будущем. Ту же информацию можно получить из runtime/debug.ReadBuildInfo
.
Значение каждой строки в таблице определяется словом в первом столбце.
- path: путь к основному пакету, использованному для сборки исполняемого файла.
- mod: модуль, содержащий основной пакет. Столбцы соответственно представляют путь к модулю, версию и сумму. Основной модуль имеет версию (
devel
) и не имеет суммы. - dep: модуль, который предоставил один или несколько пакетов, связанных с исполняемым файлом. Тот же формат, что и
mod
. - =>: замена модуля в предыдущей строке. Если замена является локальным каталогом, то указывается только путь к каталогу (без версии и суммы). Если замена является версией модуля, то указываются путь, версия и сумма, как в
mod
иdep
. Замененный модуль не имеет суммы.
go clean -modcache
Использование:
go clean [-modcache]
- Флаг
-modcache
заставляетgo clean
удалить весь кэш модулей, включая распакованный исходный код версионных зависимостей.
Обычно это лучший способ удалить кэш модулей. По умолчанию большинство файлов и каталогов в кэше модулей доступны только для чтения, чтобы тесты и редакторы не могли непреднамеренно изменить файлы после их аутентификации. К сожалению, это приводит к сбою таких команд, как
rm -r
, поскольку файлы не могут быть удалены без предварительного предоставления права на запись в их родительские каталоги.
- Флаг
-modcacherw
(принимаемыйgo build
и другими командами, поддерживающими модули) приводит к тому, что новые каталоги в кэше модулей становятся доступными для записи. Чтобы передать-modcacherw
всем командам, поддерживающим модули, добавьте его в переменнуюGOFLAGS
.
GOFLAGS
может быть установлена в среде или с помощью go env -w
. Например, приведенная ниже команда устанавливает ее навсегда:
go env -w GOFLAGS=-modcacherw
-modcacherw
следует использовать с осторожностью; разработчики должны быть осторожны и не вносить изменения в файлы в кэше модулей.
go mod verify
можно использовать для проверки соответствия файлов в кэше хэшам в файле go.sum
основного модуля.
Запросы версии
Несколько команд позволяют указать версию модуля с помощью запроса версии, который появляется после символа @
, следующего за путем к модулю или пакету в командной строке.
Примеры:
go get example.com/m@latest
go mod download example.com/m@master
go list -m -json example.com/m@e3702bed2
Запрос версии может быть одним из следующих:
- Полностью указанная семантическая версия, такая как
v1.2.3
, которая выбирает конкретную версию. Синтаксис см. в разделе «Версии». - Префикс семантической версии, такой как
v1
илиv1.2
, который выбирает самую высокую доступную версию с этим префиксом. - Сравнение семантических версий, например
<v1.2.3
или>=v1.5.6
, которое выбирает ближайшую доступную версию к объекту сравнения (самую низкую версию для>
и>=
и самую высокую версию для<
и<=
). - Идентификатор ревизии для базового репозитория исходного кода, например префикс хеша коммита, тег ревизии или имя ветки. Если ревизия помечена семантической версией, этот запрос выбирает эту версию. В противном случае этот запрос выбирает псевдоверсию для базового коммита. Обратите внимание, что ветки и теги с именами, совпадающими с другими запросами версий, не могут быть выбраны таким образом. Например, запрос
v2
выбирает последнюю версию, начинающуюся сv2
, а не ветку с именемv2
. - Строка
latest
, которая выбирает самую последнюю доступную версию релиза. Если версий релиза нет,latest
выбирает самую последнюю предрелизную версию. Если нет помеченных версий,latest
выбирает псевдоверсию для коммита в конце ветки по умолчанию репозитория. - Строка
upgrade
, которая похожа наlatest
, за исключением того, что если модуль в настоящее время требуется в более высокой версии, чем та, которую выбрала быlatest
(например, предварительная версия),upgrade
выберет текущую версию. - Строка
patch
, которая выбирает последнюю доступную версию с теми же номерами основной и второстепенной версий, что и текущая требуемая версия. Если в настоящее время не требуется никакая версия,patch
эквивалентнаlatest
. Начиная с Go 1.16, go get требует текущую версию при использовании patch (но флаг-u=patch
не имеет этого требования).
За исключением запросов на конкретные именованные версии или ревизии, все запросы учитывают доступные версии, указанные в go list -m -versions
(см. go list -m
). Этот список содержит только тегированные версии, а не псевдоверсии. Версии модулей, запрещенные директивами exclude
в файле go.mod
основного модуля, не учитываются. Версии, на которые распространяются директивы retract
в файле go.mod
из последней версии того же модуля, также игнорируются, за исключением случаев, когда флаг -retracted
используется с go list -m
и за исключением случаев загрузки директив retract
.
Релизные версии предпочтительнее предварительных версий. Например, если доступны версии v1.2.2
и v1.2.3-pre
, последний запрос выберет v1.2.2
, даже если v1.2.3-pre
выше. Запрос <v1.2.4
также выберет v1.2.2
, даже если v1.2.3-pre
ближе к v1.2.4
. Если нет доступных релизных или предварительных версий, запросы latest
, upgrade
и patch
выберут псевдоверсию для коммита в конце ветки по умолчанию репозитория. Другие запросы выдадут ошибку.
Команды модуля вне модуля
Команды Go, поддерживающие модули, обычно запускаются в контексте главного модуля, определенного файлом go.mod
в рабочем каталоге или родительском каталоге. Некоторые команды могут запускаться в режиме поддержки модулей без файла go.mod, но большинство команд работают по-разному или выдают ошибку, если файл go.mod
отсутствует.
См. Команды, поддерживающие модули для получения информации о включении и отключении режима поддержки модулей.
Команда | Поведение |
---|---|
go build | |
go doc | |
go fix | |
go fmt | |
go generate | Только пакеты из стандартной библиотеки и пакеты, указанные в командной строке как файлы .go, могут быть загружены, импортированы и скомпилированы. Пакеты из других модулей не могут быть скомпилированы, поскольку нет места для записи требований модулей и обеспечения детерминированной компиляции. |
go install | |
go list | |
go run | |
go test | |
go vet | |
go get | Пакеты и исполняемые файлы могут быть скомпилированы и установлены как обычно. Обратите внимание, что при запуске go get без файла go.mod нет главного модуля, поэтому директивы replace и exclude не применяются. |
go list -m | Для большинства аргументов требуются явные запросы версии, за исключением случаев, когда используется флаг -versions. |
go mod download | Для большинства аргументов требуются явные запросы версии. |
go mod edit | Требуется явный аргумент файла. |
go mod graph | |
go mod tidy | |
go mod vendor | Эти команды требуют файл go.mod и выдают ошибку, если он отсутствует. |
go mod verify | |
go mod why |
go work init
Использование:
go work init [moddirs]
In
it инициализирует и записывает новый файл go.work
в текущем каталоге, фактически создавая новую рабочую область в текущем каталоге.
go work init
опционально принимает пути к модулям рабочей области в качестве аргументов. Если аргумент опущен, будет создана пустая рабочая область без модулей.
Каждый путь аргумента добавляется в директиву use в файле go.work
. Текущая версия go также будет указана в файле go.work
.
go work edit
Использование:
go work edit [флаги редактирования] [go.work]
Команда go work edit
предоставляет интерфейс командной строки для редактирования go.work
, предназначенный в первую очередь для использования инструментами или скриптами.
- Она только читает
go.work
; - она не ищет информацию о вовлеченных модулях.
Если файл не указан, Edit
ищет файл go.work
в текущем каталоге и его родительских каталогах
Флаги редактирования определяют последовательность операций редактирования.
- Флаг
-fmt
переформатирует файлgo.work
без внесения других изменений. Это переформатирование также подразумевается при любых других изменениях, которые используют или перезаписывают файлgo.work
. Этот флаг необходим только в том случае, если не указаны другие флаги, как в «go work edit -fmt
». - Флаги
-use=path
и-dropuse=path
добавляют и удаляют директивуuse
из набора каталогов модулей файлаgo.work
. - Флаг
-replace=old[@v]=new[@v]
добавляет замену заданной пары пути модуля и версии. Если@v
вold@v
опущено, добавляется замена без версии в левой части, которая применяется ко всем версиям старого пути модуля. Если@v
вnew@v
опущено, новый путь должен быть локальным корневым каталогом модуля, а не путем модуля. Обратите внимание, что-replace
переопределяет любые избыточные замены дляold[@v]
, поэтому опущение@v
приведет к удалению существующих замен для определенных версий. - Флаг
-dropreplace=old[@v]
удаляет замену заданного пути модуля и пары версий. Если@v
опущено, удаляется замена без версии в левой части. - Флаг
-go=version
устанавливает ожидаемую версию языка Go.
Флаги редактирования могут повторяться. Изменения применяются в указанном порядке.
go work edit
имеет дополнительные флаги, которые контролируют его вывод
- Флаг
-print
выводит окончательныйgo.work
в текстовом формате вместо записи обратно вgo.mod
. - Флаг
-json
выводит окончательный файлgo.work
в формате JSON вместо записи обратно вgo.mod
. Вывод JSON соответствует следующим типам Go:
type Module struct {
Path string
Version string
}
type GoWork struct {
Go string
Directory []Directory
Replace []Replace
}
type Use struct {
Path string
ModulePath string
}
type Replace struct {
Old Module
New Module
}
go work use
Использование:
go work use [-r] [moddirs]
Команда go work use
предоставляет интерфейс командной строки для добавления каталогов, по желанию рекурсивно, в файл go.work
.
Директива use
будет добавлена в файл go.work
для каждого каталога, указанного в командной строке go.work
, если он существует на диске, или удалена из файла go.work
, если он не существует на диске.
- Флаг
-r
рекурсивно ищет модули в указанных каталогах, и командаuse
работает так, как если бы каждый из каталогов был указан в качестве аргумента.
go work sync
Использование:
go work sync
Команда go work sync
синхронизирует список сборок рабочего пространства с модулями рабочего пространства.
Список сборок рабочего пространства - это набор версий всех (переходных) зависимых модулей, используемых для выполнения сборок в рабочем пространстве. go work sync
генерирует этот список сборок, используя алгоритм минимального выбора версий (MVS
), а затем синхронизирует эти версии с каждым из модулей, указанных в рабочем пространстве (с помощью директив use
).
После того как список сборок рабочего пространства вычислен, файл go.mod
для каждого модуля в рабочем пространстве переписывается с обновлением зависимостей, относящихся к этому модулю, чтобы соответствовать списку сборок рабочего пространства. Обратите внимание, что минимальный выбор версий гарантирует, что версия каждого модуля в списке сборки всегда будет такой же или выше, чем в каждом модуле рабочего пространства.
Прокси-модули
Протокол GOPROXY
Прокси-модуль — это HTTP-сервер, который может отвечать на запросы GET
для указанных ниже путей. Запросы не содержат параметров запроса и не требуют специальных заголовков, поэтому даже сайт, обслуживающийся из фиксированной файловой системы (включая URL file://), может быть прокси-модулем.
Успешные HTTP-ответы должны иметь статус-код 200 (OK). Перенаправления (3xx) принимаются. Ответы с кодами состояния 4xx и 5xx рассматриваются как ошибки. Коды ошибок 404 (Not Found) и 410 (Gone) указывают, что запрошенный модуль или версия недоступны на прокси, но могут быть найдены в другом месте. Ответы с ошибками должны иметь тип содержимого text/plain
с кодировкой utf-8 или us-ascii.
Команда go
может быть настроена для связи с прокси-серверами или серверами контроля версий с помощью переменной среды GOPROXY
, которая принимает список URL-адресов прокси-серверов.
Список может включать ключевые слова direct
или off
(подробности см. в разделе «Переменные среды»).
Элементы списка могут быть разделены запятыми (,
) или вертикальными чертами (|
), которые определяют поведение при ошибке.
Когда за URL следует запятая, команда go
переходит к более поздним источникам только после ответа 404 (Not Found) или 410 (Gone).
Когда за URL следует вертикальная черта, команда go
переходит к более поздним источникам после любой ошибки, включая не-HTTP ошибки, такие как таймауты.
Такое поведение при обработке ошибок позволяет прокси действовать как шлюз для неизвестных модулей.
Например, прокси может ответить ошибкой 403 (Forbidden) для модулей, не входящих в утвержденный список (см. Частный прокси, обслуживающий частные модули).
В таблице ниже указаны запросы, на которые должен отвечать прокси модуля. Для каждого пути $base
— это часть пути URL-адреса прокси, $module
— путь модуля, а $version
— версия.
Например, если URL-адрес прокси-сервера —
https://example.com/mod
, а клиент запрашивает файл go.mod для модуляgolang.org/x/text
версииv0.3.2
, клиент отправит запросGET
наhttps://example.com/mod/golang.org/x/text/@v/v0.3.2.mod
.
Чтобы избежать неоднозначности при обслуживании из файловых систем, нечувствительных к регистру, элементы $module
и $version
кодируются с учетом регистра, заменяя каждую заглавную букву восклицательным знаком, за которым следует соответствующая строчная буква. Это позволяет хранить на диске модули example.com/M
и example.com/m
, поскольку первый кодируется как example.com/!m
.
Путь | Описание |
---|---|
$base/$module/@v/list |
Возвращает список известных версий данного модуля в виде простого текста, по одной на строку. Этот список не должен включать псевдоверсии. Возвращает метаданные в формате JSON о конкретной версии модуля. Ответ должен быть объектом JSON, соответствующим приведенной ниже структуре данных Go: |
type Info struct {
Version string // строка версии
Time time.Time // время фиксации
}
Путь | Описание |
---|---|
$base/$module/@v/$version.info |
Поле Version является обязательным и должно содержать действительную каноническую версию (см. Версии). $version в пути запроса не обязательно должна быть той же версией или даже действительной версией; этот конечный пункт может использоваться для поиска версий для имен ветвей или идентификаторов ревизий. Однако, если $version является канонической версией с основной версией, совместимой с $module , поле Version в успешном ответе должно быть таким же. Поле Time является необязательным. Если оно присутствует, оно должно быть строкой в формате RFC 3339. Оно указывает время создания версии. В будущем могут быть добавлены дополнительные поля, поэтому другие имена зарезервированы. |
$base/$module/@v/$version.mod |
Возвращает файл go.mod для определенной версии модуля. Если модуль не имеет файла go.mod для запрошенной версии, должен быть возвращен файл, содержащий только оператор модуля с запрошенным путем к модулю. В противном случае должен быть возвращен исходный, немодифицированный файл go.mod . |
$base/$module/@v/$version.zip |
Возвращает zip-файл, содержащий содержимое определенной версии модуля. См. раздел «Zip-файлы модулей» для получения подробной информации о том, как должен быть отформатирован этот zip-файл. |
$base/$module/@latest |
Возвращает метаданные в формате JSON о последней известной версии модуля в том же формате, что и $base/$module/@v/$version.info . Последняя версия должна быть версией модуля, которую команда go должна использовать, если $base/$module/@v/list пуст или ни одна из перечисленных версий не подходит. Этот конечный пункт является опциональным, и прокси-серверы модулей не обязаны его реализовывать. |
При определении последней версии модуля команда go
запрашивает $base/$module/@v/list
, затем, если подходящих версий не найдено, $base/$module/@latest
.
Команда go
предпочитает в порядке убывания: семантически наивысшую релизную версию, семантически наивысшую предрелизную версию и хронологически самую последнюю псевдо-версию. В Go 1.12 и более ранних версиях команда go
считала псевдоверсии в $base/$module/@v/list
предрелизными версиями, но начиная с Go 1.13 это уже не так.
Прокси модуляь должен всегда предоставлять одно и то же содержимое для успешных ответов на запросы $base/$module/$version.mod
и $base/$module/$version.zip
. Это содержимое проходит криптографическую проверку подлинности с помощью файлов go.sum
и, по умолчанию, базы данных контрольных сумм.
Команда go
кэширует большую часть содержимого, загружаемого с прокси модулей, в своем кэше модулей в $GOPATH/pkg/mod/cache/download
. Даже при загрузке непосредственно из систем контроля версий команда go синтезирует явные файлы info
, mod
и zip
и сохраняет их в этом каталоге, как если бы она загружала их непосредственно с прокси. Расположение кэша совпадает с пространством URL прокси, поэтому, обслуживая $GOPATH/pkg/mod/cache/download
по адресу (или копируя его на) https://example.com/proxy
, пользователи смогут получить доступ к кэшированным версиям модулей, установив GOPROXY
на https://example.com/proxy
.
Взаимодействие с прокси
Команда go
может загружать исходный код модулей и метаданные из прокси модулей. Переменная окружения GOPROXY
может использоваться для настройки прокси, к которым команда go
может подключаться, а также для определения, может ли она напрямую взаимодействовать с системами контроля версий. Загруженные данные модулей сохраняются в кэше модулей. Команда go
связывается с прокси только в том случае, если ей требуется информация, которой нет в кэше.
В разделе «Протокол GOPROXY
» описаны запросы, которые могут отправляться на сервер GOPROXY
. Однако также полезно понимать, когда команда go
отправляет эти запросы. Например, go build
выполняет следующую процедуру:
- Вычисляет список сборки, читая файлы
go.mod
и выполняя минимальный выбор версии (MVS). - Считывает пакеты, указанные в командной строке, и пакеты, которые они импортируют.
- Если пакет не предоставляется ни одним модулем в списке сборки, находит модуль, который его предоставляет. Добавляет требование модуля в его последней версии в
go.mod
и начинает заново. - Строит пакеты после того, как все загружено.
Когда команда go
вычисляет список сборки, она загружает файл go.mod
для каждого модуля в графе модулей.
Если файл go.mod
отсутствует в кэше, команда go
загрузит его из прокси с помощью запроса $module/@v/$version.mod
(где $module
— путь к модулю, а $version
— версия).
Эти запросы можно протестировать с помощью такого инструмента, как curl
. Например, приведенная ниже команда загружает файл go.mod
для golang.org/x/mod
версии v0.2.0
:
$ curl https://proxy.golang.org/golang.org/x/mod/@v/v0.2.0.mod
module golang.org/x/mod
go 1.12
require (
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898
)
Чтобы загрузить пакет, команде go
нужен исходный код модуля, который его предоставляет. Исходный код модуля распространяется в файлах .zip
, которые извлекаются в кэш модулей. Если .zip
модуля нет в кэше, команда go
загрузит его с помощью запроса $module/@v/$version.zip
.
$ curl -O https://proxy.golang.org/golang.org/x/mod/@v/v0.2.0.zip
$ unzip -l v0.2.0.zip | head
Archive: v0.2.0.zip
Length Date Time Name
--------- ---------- ----- ----
1479 00-00-1980 00:00 golang.org/x/mod@v0.2.0/LICENSE
1303 00-00-1980 00:00 golang.org/x/mod@v0.2.0/PATENTS
559 00-00-1980 00:00 golang.org/x/mod@v0.2.0/README
21 00-00-1980 00:00 golang.org/x/mod@v0.2.0/codereview.cfg
214 00-00-1980 00:00 golang.org/x/mod@v0.2.0/go.mod
1476 00-00-1980 00:00 golang.org/x/mod@v0.2.0/go.sum
5224 00-00-1980 00:00 golang.org/x/mod@v0.2.0/gosumcheck/main.go
Обратите внимание, что запросы .mod
и .zi
p являются отдельными, даже если файлы go.mod
обычно содержатся в файлах .zip
. Команде go
может потребоваться загрузить файлы go.mod
для многих различных модулей, а файлы .mod
намного меньше по размеру, чем файлы .zip
. Кроме того, если в проекте Go нет файла go.mod, прокси будет предоставлять синтетический файл go.mod, содержащий только директиву модуля. Синтетические файлы go.mod
генерируются командой go
при загрузке из системы контроля версий.
Если команде go
необходимо загрузить пакет, который не предоставляется ни одним модулем в списке сборки, она попытается найти новый модуль, который его предоставляет. Этот процесс описан в разделе «Преобразование пакета в модуль». Вкратце, команда go запрашивает информацию о последней версии каждого пути модуля, который может содержать пакет.
Например, для пакета golang.org/x/net/html
команда go
попытается найти последние версии модулей golang.org/x/net/html
, golang.org/x/net
, golang.org/x/
и golang.org
. Только golang.org/x/net
действительно существует и предоставляет этот пакет, поэтому команда go
использует последнюю версию этого модуля.
Если пакет предоставляется более чем одним модулем, команда go
использует модуль с самым длинным путем.
Когда команда go
запрашивает последнюю версию модуля, она сначала отправляет запрос на $module/@v/list
. Если список пуст или ни одна из возвращенных версий не может быть использована, она отправляет запрос на $module/@latest
. После выбора версии команда go
отправляет запрос $module/@v/$version.info
для получения метаданных. Затем она может отправить запросы $module/@v/$version.mod
и $module/@v/$version.zip
для загрузки файла go.mod
и исходного кода.
$ curl https://proxy.golang.org/golang.org/x/mod/@v/list
v0.1.0
v0.2.0
$ curl https://proxy.golang.org/golang.org/x/mod/@v/v0.2.0.info
{«Version»:«v0.2.0»,„Time“:«2020-01-02T17:33:45Z»}
После загрузки файла .mod
или .zip
команда go
вычисляет криптографический хеш и проверяет, соответствует ли он хешу в файле go.sum
основного модуля. Если хеш отсутствует в go.sum
, по умолчанию команда go
извлекает его из базы данных контрольных сумм.
Если вычисленный хеш не совпадает, команда go сообщает об ошибке безопасности и не устанавливает файл в кэш модулей. Переменные среды GOPRIVATE
и GONOSUMDB
могут использоваться для отключения запросов к базе данных контрольных сумм для определенных модулей.
Переменная среды GOSUMDB
также может быть установлена в значение off
, чтобы полностью отключить запросы к базе данных контрольных сумм.
Дополнительные сведения см. в разделе Аутентификация модулей. Обратите внимание, что списки версий и метаданные версий, возвращаемые для запросов .info
, не аутентифицируются и могут изменяться со временем.
Обслуживание модулей напрямую из прокси
Большинство модулей разрабатываются и обслуживаются из репозитория системы контроля версий.
В прямом режиме команда go
загружает такой модуль с помощью инструмента контроля версий (см. Системы контроля версий). Также можно обслуживать модуль напрямую из прокси модуля. Это полезно для организаций, которые хотят обслуживать модули, не раскрывая свои серверы контроля версий, а также для организаций, которые используют инструменты контроля версий, не поддерживаемые командой go
.
Когда команда go
загружает модуль в прямом режиме, она сначала ищет URL-адрес сервера модулей с помощью HTTP-запроса GET на основе пути модуля.
Она ищет тег <meta>
с именем go-import
в HTML-ответе. Содержимое тега должно содержать корневой путь репозитория, систему контроля версий и URL-адрес, разделенные пробелами. Подробнее см. в разделе Поиск репозитория для пути модуля.
Если системой контроля версий является mod
, команда go
загружает модуль с указанного URL-адреса с помощью протокола GOPROXY
.
Например, предположим, что команда
go
пытается загрузить модульexample.com/gopher
версииv1.0.0
. Она отправляет запрос наhttps://example.com/gopher?go-get=1
. Сервер отвечает HTML-документом, содержащим тег:
<meta name="go-import" content="example.com/gopher mod https://modproxy.example.com">
На основании этого ответа команда go загружает модуль, отправляя запросы на https://modproxy.example.com/example.com/gopher/@v/v1.0.0.info
, v1.0.0.mod
и v1.0.0.zip
.
Обратите внимание, что модули, обслуживаемые непосредственно с прокси, не могут быть загружены с помощью go get
в режиме GOPATH
.
Системы контроля версий
Команда go
может загружать исходный код модулей и метаданные непосредственно из репозитория системы контроля версий. Загрузка модуля через прокси-сервер обычно происходит быстрее, но прямое подключение к репозиторию необходимо, если прокси-сервер недоступен или если репозиторий модуля недоступен для прокси-сервера (часто это относится к частным репозиториям). Поддерживаются Git
, Subversion
, Mercurial
, Bazaar
и Fossil
. Чтобы команда go
могла использовать инструмент контроля версий, он должен быть установлен в каталоге, включенном в PATH
.
Чтобы загружать определенные модули из репозиториев исходного кода, а не через прокси, установите переменные окружения GOPRIVATE
или GONOPROXY
. Чтобы настроить команду go
на загрузку всех модулей напрямую из репозиториев исходного кода, установите GOPROXY
в значение direct
. Дополнительные сведения см. в разделе Переменные окружения.
Поиск репозитория для пути модуля
Когда команда go
загружает модуль в прямом режиме, она сначала находит репозиторий, содержащий модуль.
Если путь к модулю имеет квалификатор VCS
(один из .bzr, .fossil, .git, .hg, .svn
) в конце компонента пути, команда go
будет использовать все до этого квалификатора пути в качестве URL-адреса репозитория. Например, для модуля example.com/foo.git/bar
команда go
загружает репозиторий по адресу example.com/foo
с помощью git
, ожидая найти модуль в подкаталоге bar
. Команда go
угадывает протокол, который следует использовать, на основе протоколов, поддерживаемых инструментом контроля версий.
Если путь модуля не имеет квалификатора, команда go
отправляет HTTP-запрос GET на URL, полученный из пути модуля с строкой запроса ?go-get=1
. Например, для модуля golang.org/x/mod
команда go
может отправить следующие запросы:
https://golang.org/x/mod?go-get=1 (preferred)
http://golang.org/x/mod?go-get=1 (fallback, only with GOINSECURE)
Команда go
следует за перенаправлениями, но игнорирует коды статуса ответа, поэтому сервер может ответить кодом 404 или любым другим кодом ошибки. Переменная среды GOINSECURE
может быть установлена, чтобы разрешить переход на незашифрованный HTTP для определенных модулей.
Сервер должен отвечать HTML-документом, содержащим тег <meta>
в <head>
документа.
Тег <meta>
должен появляться в начале документа, чтобы не сбивать с толку ограниченный парсер команды go
. В частности, он должен появляться перед любым необработанным JavaScript
или CSS
. Тег <meta>
должен иметь следующий вид:
<meta name="go-import" content="root-path vcs repo-url [subdirectory]">
- root-path — это корневой путь репозитория, часть пути модуля, которая соответствует корневому каталогу репозитория или подкаталогу, если он присутствует и используется Go 1.25 или более поздней версии (см. раздел о подкаталогах ниже). Он должен быть префиксом или точно соответствовать запрошенному пути модуля. Если он не соответствует точно, делается другой запрос на префикс, чтобы проверить соответствие тегов
<meta>
. - vcs — это система контроля версий. Это должен быть один из инструментов, перечисленных в таблице ниже, или ключевое слово
mod
, которое указывает команде go загрузить модуль с указанного URL-адреса с использованием протоколаGOPROXY
. Подробности см. в разделе «Обслуживание модулей напрямую с прокси». - repo-url — это URL-адрес репозитория. Если URL не содержит схему (либо потому, что путь к модулю имеет квалификатор
VCS
, либо потому, что в теге<meta>
отсутствует схема), команда go попробует каждый протокол, поддерживаемый системой контроля версий. Например, сGit
командаgo
попробуетhttps://
, а затемgit+ssh://
. Небезопасные протоколы (такие какhttp://
иgit://
) могут использоваться только в том случае, если путь к модулю соответствует переменной средыGOINSECURE
. - Подкаталог, если он присутствует, является подкаталогом репозитория, разделенным косой чертой, которому соответствует root-path, переопределяя по умолчанию корневой каталог репозитория. Мета-теги go-import, предоставляющие подкаталог, распознаются только Go 1.25 и более поздними версиями. Попытки извлечь модули в более ранних версиях Go будут игнорировать мета-тег и приведут к сбою разрешения, если модуль не может быть разрешен в другом месте.
Name | Command | GOVCS default | Secure schemes |
---|---|---|---|
Bazaar | bzr | Private only | https, bzr+ssh |
Fossil | fossil | Private only | https |
Git | git | Public and private | https, git+ssh, ssh |
Mercurial | hg | Public and private | https, ssh |
Subversion | svn | Private only | https, svn+ssh |
В качестве примера снова рассмотрим golang.org/x/mod
. Команда go отправляет запрос на https://golang.org/x/mod?go-get=1
. Сервер отвечает HTML-документом, содержащим тег:
<meta name="go-import" content="golang.org/x/mod git https://go.googlesource.com/mod">
На основании этого ответа команда go будет использовать репозиторий Git по удаленному URL-адресу https://go.googlesource.com/mod
.
GitHub
и другие популярные хостинговые сервисы отвечают на запросы ?go-get=1
для всех репозиториев, поэтому обычно для модулей, размещенных на этих сайтах, не требуется настройка сервера.
После нахождения URL-адреса репозитория команда go клонирует репозиторий в кэш модулей. Как правило, команда go
старается избегать извлечения ненужных данных из репозитория. Однако фактические используемые команды варьируются в зависимости от системы контроля версий и могут меняться со временем. Для Git
команда go
может перечислить большинство доступных версий без загрузки коммитов. Обычно она извлекает коммиты без загрузки коммитов предков, но иногда это необходимо.
Сопоставление версий с коммитами
Команда go
может проверить модуль в репозитории с определенной канонической версией, такой как v1.2.3
, v2.4.0-beta
или v3.0.0+incompatible
. Каждая версия модуля должна иметь семантический тег версии в репозитории, который указывает, какая ревизия должна быть проверена для данной версии.
Если модуль определен в корневом каталоге репозитория или в подкаталоге основной версии корневого каталога, то каждое имя тега версии равно соответствующей версии. Например, модуль golang.org/x/text
определен в корневом каталоге своего репозитория, поэтому версия v0.3.2
имеет тег v0.3.2
в этом репозитории. Это верно для большинства модулей.
Если модуль определен в подкаталоге внутри репозитория, то есть часть пути модуля, относящаяся к подкаталогу модуля, не пуста, то каждое имя тега должно начинаться с префикса подкаталога модуля, за которым следует косая черта. Например, модуль golang.org/x/tools/gopls
определен в подкаталоге gopls
репозитория с корневым путем golang.org/x/tools
. Версия v0.4.0
этого модуля должна иметь тег с именем gopls/v0.4.0
в этом репозитории.
Номер основной версии тега семантической версии должен соответствовать суффиксу основной версии пути модуля (если таковой имеется). Например, тег v1.0.0
может принадлежать модулю example.com/mod
, но не example.com/mod/v2
, который будет иметь теги типа v2.0.0
.
Теги с основной версией v2
или выше могут принадлежать модулю без суффикса основной версии, если файл go.mod
отсутствует, а модуль находится в корневом каталоге репозитория. Такая версия обозначается суффиксом +incompatible
. Сам тег версии не должен иметь суффикса. См. раздел «Совместимость с репозиториями, не являющимися модулями».
После создания тег не должен удаляться или изменяться на другую ревизию. Версии проходят аутентификацию для обеспечения безопасных и повторяемых сборок. Если тег изменен, клиенты могут увидеть ошибку безопасности при его загрузке. Даже после удаления тега его содержимое может оставаться доступным на прокси-серверах модулей.
Сопоставление псевдоверсий с коммитами
Команда go
может проверить модуль в репозитории с определенной ревизией, закодированной как псевдоверсия, например v1.3.2-0.20191109021931-daa7c04131f5
.
Последние 12 символов псевдоверсии (daa7c04131f5
в примере выше) указывают на ревизию в репозитории, которую необходимо проверить. Значение этого зависит от системы контроля версий. Для Git
и Mercurial
это префикс хеша коммита. Для Subversion
это номер ревизии с нулевым заполнением.
Перед проверкой коммита команда go проверяет, что временная метка (20191109021931
выше) соответствует дате коммита. Она также проверяет, что базовая версия (v1.3.1
, версия перед v1.3.2
в примере выше) соответствует семантическому тегу версии, который является предком коммита. Эти проверки гарантируют, что авторы модулей имеют полный контроль над тем, как псевдоверсии сопоставляются с другими выпущенными версиями.
Дополнительную информацию см. в разделе Псевдоверсии.
Сопоставление веток и коммитов с версиями
Модуль может быть проверен в определенной ветке, теге или ревизии с помощью запроса версии.
go get example.com/mod@master
Команда go
преобразует эти имена в канонические версии, которые можно использовать с минимальным выбором версии (MVS
). MVS
зависит от возможности однозначно упорядочить версии. Имена веток и ревизии не могут быть надежно сопоставлены во времени, поскольку они зависят от структуры репозитория, которая может изменяться.
Если ревизия помечена одним или несколькими семантическими тегами версии, такими как v1.2.3
, будет использован тег для самой высокой действительной версии. Команда go
учитывает только семантические теги версии, которые могут принадлежать целевому модулю; например, тег v1.5.2
не будет учитываться для example.com/mod/v2
, поскольку основная версия не соответствует суффиксу пути модуля.
Если ревизия не помечена действительным тегом семантической версии, команда go
сгенерирует псевдоверсию. Если у ревизии есть предки с действительными тегами семантической версии, в качестве базы псевдоверсии будет использована версия самого старшего предка. См. Псевдоверсии.
Каталоги модулей в репозитории
После того, как репозиторий модуля был проверен на определенную ревизию, команда go должна найти каталог, содержащий файл go.mod
модуля (корневой каталог модуля).
Напомним, что путь к модулю состоит из трех частей: корневой путь репозитория (соответствующий корневому каталогу репозитория), подкаталог модуля и суффикс основной версии (только для модулей, выпущенных в версии v2 или выше).
Для большинства модулей путь к модулю равен корневому пути репозитория, поэтому корневой каталог модуля является корневым каталогом репозитория.
Иногда модули определяются в подкаталогах репозитория. Обычно это делается для больших репозиториев с несколькими компонентами, которые необходимо выпускать и версионировать независимо друг от друга. Такой модуль должен находиться в подкаталоге, который соответствует части пути к модулю после корневого пути репозитория. Например, предположим, что модуль example.com/monorepo/foo/bar
находится в репозитории с корневым путем example.com/monorepo
. Его файл go.mod
должен находиться в подкаталоге foo/bar
.
Если модуль выпускается в основной версии v2
или выше, его путь должен иметь суффикс основной версии. Модуль с суффиксом основной версии может быть определен в одном из двух подкаталогов: одном с суффиксом и одном без него. Например, предположим, что новая версия вышеуказанного модуля выпущена с путем example.com/monorepo/foo/bar/v2
. Его файл go.mod
может находиться либо в foo/bar
, либо в foo/bar/v2
.
Подкаталоги с суффиксом основной версии являются подкаталогами основной версии. Они могут использоваться для разработки нескольких основных версий модуля в одной ветке. Это может быть ненужным, когда разработка нескольких основных версий ведется в отдельных ветках. Однако подкаталоги основной версии имеют важное свойство: в режиме GOPATH
пути импорта пакетов точно соответствуют каталогам в GOPATH/src
. Команда go
обеспечивает минимальную совместимость модулей в режиме GOPATH
(см. Совместимость с репозиториями, не являющимися модулями), поэтому подкаталоги основной версии не всегда необходимы для совместимости с проектами, созданными в режиме GOPATH
. Однако у старых инструментов, которые не поддерживают минимальную совместимость модулей, могут возникнуть проблемы.
Как только команда go
находит корневой каталог модуля, она создает файл .zip
с содержимым каталога, а затем извлекает файл .zip
в кэш модуля. См. Ограничения по пути и размеру файлов для получения подробной информации о том, какие файлы могут быть включены в файл .zip
. Содержимое файла .zip
проверяется перед извлечением в кэш модуля так же, как если бы файл .zip
был загружен с прокси-сервера.
Файлы zip
модулей не включают содержимое каталогов поставщиков или вложенных модулей (подкаталогов, содержащих файлы go.mod
). Это означает, что модуль не должен ссылаться на файлы, расположенные за пределами своего каталога или в других модулях. Например, шаблоны //go:embed
не должны совпадать с файлами во вложенных модулях. Такое поведение может служить полезным обходным путем в ситуациях, когда файлы не должны включаться в модуль. Например, если в репозитории есть большие файлы, зарегистрированные в каталоге testdata
, автор модуля может добавить пустой файл go.mod
в testdata
, чтобы пользователи не должны были загружать эти файлы. Конечно, это может уменьшить охват для пользователей, тестирующих свои зависимости.
Особый случай для файлов LICENSE
Когда команда go
создает файл .zip
для модуля, который не находится в корневом каталоге репозитория, если в корневом каталоге модуля (рядом с go.mod
) нет файла с именем LICENSE
, команда go
скопирует файл с именем LICENSE
из корневого каталога репозитория, если он присутствует в той же ревизии.
Этот особый случай позволяет применять один и тот же файл LICENSE
ко всем модулям в репозитории. Это относится только к файлам с именем LICENSE
, без расширений, таких как .txt
. К сожалению, это нельзя расширить без нарушения криптографических сумм существующих модулей; см. Аутентификация модулей. Другие инструменты и веб-сайты, такие как pkg.go.dev
, могут распознавать файлы с другими именами.
Обратите также внимание, что команда go
не включает символические ссылки при создании файлов .zip
модулей; см. Ограничения по пути и размеру файлов. Следовательно, если в корневом каталоге репозитория нет файла LICENSE
, авторы могут вместо этого создать копии своих файлов лицензий в модулях, определенных в подкаталогах, чтобы обеспечить включение этих файлов в файлы .zip
модулей.
Управление инструментами контроля версий с помощью GOVCS
Возможность команды go
загружать модули с помощью команд контроля версий, таких как git
, имеет решающее значение для децентрализованной экосистемы пакетов, в которой код может быть импортирован с любого сервера. Это также может представлять потенциальную угрозу безопасности, если злоумышленный сервер найдет способ заставить вызванную команду контроля версий выполнить непреднамеренный код.
Чтобы сбалансировать функциональность и проблемы безопасности, команда go
по умолчанию будет использовать только git
и hg
для загрузки кода с публичных серверов. Она будет использовать любую известную систему контроля версий для загрузки кода с частных серверов, определенных как те, которые хостят пакеты, соответствующие переменной среды GOPRIVATE
. Причина, по которой разрешены только Git
и Mercurial
, заключается в том, что эти две системы уделяют наибольшее внимание проблемам запуска в качестве клиентов недоверенных серверов. В отличие от них, Bazaar
, Fossil
и Subversion
в основном используются в доверенных, аутентифицированных средах и не подвергаются столь тщательному анализу с точки зрения уязвимостей.
Ограничения команд управления версиями применяются только при использовании прямого доступа к управлению версиями для загрузки кода. При загрузке модулей с прокси-сервера команда go
использует протокол GOPROXY
, который всегда разрешен. По умолчанию команда go использует зеркало модулей Go (proxy.golang.org)
для общедоступных модулей и переключается на управление версиями только для частных модулей или когда зеркало отказывается обслуживать общедоступный пакет (обычно по юридическим причинам). Таким образом, клиенты по-прежнему могут по умолчанию получать доступ к общедоступному коду, обслуживаемому репозиториями Bazaar
, Fossil
или Subversion
, поскольку для этих загрузок используется зеркало модулей Go, которое принимает на себя риск безопасности, связанный с запуском команд системы контроля версий с использованием настраиваемой песочницы.
Переменная GOVCS
может использоваться для изменения разрешенных систем контроля версий для определенных модулей. Переменная GOVCS
применяется при сборке пакетов как в режиме с поддержкой модулей, так и в режиме GOPATH
. При использовании модулей шаблоны сопоставляются с путем модуля. При использовании GOPATH
шаблоны сопоставляются с путем импорта, соответствующим корню репозитория системы контроля версий.
Общая форма переменной GOVCS
— это разделенный запятыми список правил pattern:vcslist
. Pattern
— это шаблон glob
, который должен соответствовать одному или нескольким начальным элементам пути модуля или импорта. Vcslist
— это разделенный вертикальной чертой список разрешенных команд управления версиями, или all
, чтобы разрешить использование любой известной команды, или off
, чтобы ничего не разрешать.
Обратите внимание, что если модуль соответствует шаблону с vcslist off
, он все равно может быть загружен, если исходный сервер использует схему mod
, которая указывает команде go загрузить модуль с помощью протокола GOPROXY
. Применяется самый ранний соответствующий шаблон в списке, даже если более поздние шаблоны также могут соответствовать.
Рассмотрим, например:
GOVCS=github.com:git,evil.com:off,*:git|hg
С этой настройкой код с модулем или путем импорта, начинающимся с github.com/
, может использовать только git
; пути на evil.com
не могут использовать никакие команды управления версиями, а все остальные пути (* соответствует всему) могут использовать только git
или hg
.
Специальные шаблоны public
и private
соответствуют публичным и частным модулям или путям импорта. Путь является частным, если он соответствует переменной GOPRIVATE
; в противном случае он является публичным.
Если ни одно из правил в переменной GOVCS
не соответствует конкретному модулю или пути импорта, команда go
применяет свое правило по умолчанию, которое теперь можно обозначить в нотации GOVCS
как public:git|hg,private:all
.
Чтобы разрешить неограниченное использование любой системы контроля версий для любого пакета, используйте:
GOVCS=*:all
Чтобы отключить все использование контроля версий, используйте:
GOVCS=*:off
Команда go env -w
может быть использована для установки переменной GOVCS
для будущих вызовов команды go
.
GOVCS
был введен в Go 1.16. Более ранние версии Go могут использовать любой известный инструмент контроля версий для любого модуля.
Zip-файлы модулей
Версии модулей распространяются в виде zip
-файлов. Редко возникает необходимость в прямом взаимодействии с этими файлами, поскольку команда go
автоматически создает, загружает и извлекает их из прокси-серверов модулей и репозиториев системы контроля версий. Однако знание об этих файлах все же полезно для понимания ограничений кроссплатформенной совместимости или при реализации прокси-сервера модулей.
Команда go mod download
загружает zip
-файлы для одного или нескольких модулей, а затем извлекает эти файлы в кэш модулей. В зависимости от GOPROXY
и других переменных окружения, команда go может либо загружать zip
-файлы с прокси, либо клонировать репозитории контроля версий и создавать из них zip
-файлы. Флаг -json
может использоваться для поиска местоположения загруженных zip
-файлов и их извлеченного содержимого в кэше модулей.
Пакет golang.org/x/mod/zip
можно использовать для программного создания, извлечения или проверки содержимого zip-файлов.
Ограничения по пути к файлу и размеру
Существует ряд ограничений на содержимое zip
-файлов модулей. Эти ограничения гарантируют, что zip
-файлы могут быть безопасно и последовательно извлечены на широком спектре платформ.
- Размер
zip
-файла модуля не может превышать 500 МБ. Общий размер его файлов в несжатом виде также ограничен 500 МБ. Размер файловgo.mod
ограничен 16 МБ. ФайлыLICENSE
также ограничены 16 МБ. Эти ограничения существуют для смягчения атак типа «отказ в обслуживании» на пользователей, прокси и другие части экосистемы модулей. Репозитории, содержащие более 500 МБ файлов в дереве каталогов модулей, должны помечать версии модулей при фиксации, которые включают только файлы, необходимые для сборки пакетов модуля; видео, модели и другие большие ресурсы обычно не нужны для сборки. - Каждый файл в
zip
-файле модуля должен начинаться с префикса$module@$version/
, где$module
— это путь к модулю, а$version
— версия, например,golang.org/x/mod@v0.3.0/
. Путь к модулю должен быть действительным, версия должна быть действительной и канонической, а версия должна соответствовать суффиксу основной версии пути к модулю. Конкретные определения и ограничения см. в разделе «Пути и версии модулей». - Режимы файлов, временные метки и другие метаданные игнорируются.
- Пустые каталоги (записи с путями, заканчивающимися косой чертой) могут быть включены в
zip
-файлы модулей, но не извлекаются. Командаgo
не включает пустые каталоги в создаваемые еюzip
-файлы. - Символьные ссылки и другие нестандартные файлы игнорируются при создании
zip
-файлов, поскольку они не переносимы между операционными системами и файловыми системами, и нет переносимого способа их представления в форматеzip
-файла. - Файлы в каталогах с именем vendor игнорируются при создании
zip
-файлов, поскольку каталоги vendor вне основного модуля никогда не используются. - Файлы в каталогах, содержащих файлы
go.mod
, кроме корневого каталога модуля, игнорируются при созданииzip
-файлов, поскольку они не являются частью модуля. Командаgo
игнорирует подкаталоги, содержащие файлыgo.mod
, при извлеченииzip
-файлов. - Ни два файла в
zip
-файле не могут иметь одинаковые пути при сгибании регистра Unicode (см.strings.EqualFold
). Это гарантирует, чтоzip
-файлы могут быть извлечены в файловых системах, нечувствительных к регистру, без коллизий. - Файл
go.mod
может присутствовать или отсутствовать в каталоге верхнего уровня ($module@$version/go.mod
). Если он присутствует, он должен иметь имяgo.mod
(все строчные буквы). Файлы с именемgo.mod
не допускаются в других каталогах. - Имена файлов и каталогов в модуле могут состоять из букв Unicode, цифр ASCII, символа пробела
ASCII (U+0020)
и символов пунктуации ASCII!#$%&()+,-.=@[]^_{}~
. Обратите внимание, что пути к пакетам не могут содержать все эти символы. См.module.CheckFilePath
иmodule.CheckImportPath
для ознакомления с различиями. - Имя файла или каталога до первой точки не должно быть зарезервированным именем файла в Windows, независимо от регистра (CON, com1, NuL и т. д.).
Private (Частные модули)
Модули Go часто разрабатываются и распространяются на серверах контроля версий и прокси-серверах модулей, которые недоступны в общедоступном Интернете. Команда go
может загружать и собирать модули из частных источников, хотя для этого обычно требуется некоторая настройка.
Для настройки доступа к частным модулям можно использовать перечисленные ниже переменные окружения. Подробности см. в разделе Переменные окружения. См. также раздел Конфиденциальность для получения информации об управлении информацией, отправляемой на общедоступные серверы.
- GOPROXY — список URL-адресов прокси-серверов модулей. Команда
go
будет пытаться загрузить модули с каждого сервера по очереди. Ключевое словоdirect
указывает командеgo
загружать модули из репозиториев контроля версий, где они разрабатываются, вместо использования прокси-сервера. - GOPRIVATE — список шаблонов префиксов путей к модулям, которые должны считаться частными. Действует как значение по умолчанию для
GONOPROXY
иGONOSUMDB
. - GONOPROXY — список шаблонов
glob
префиксов путей модулей, которые не должны загружаться с прокси. Команда go загрузит соответствующие модули из репозиториев контроля версий, где они разрабатываются, независимо отGOPROXY
. - GONOSUMDB — список шаблонов
glob
префиксов путей модулей, которые не должны проверяться с помощью общедоступной базы данных контрольных суммsum.golang.org
. - GOINSECURE — список шаблонов
glob
префиксов путей модулей, которые могут быть получены черезHTTP
и другие небезопасные протоколы. Эти переменные могут быть установлены в среде разработки (например, в файле.profile
) или они могут быть установлены навсегда с помощьюgo env -w
.
В остальной части этого раздела описаны общие шаблоны для предоставления доступа к частным прокси-серверам модулей и репозиториям контроля версий.
Частный прокси-сервер, обслуживающий все модули
Центральный частный прокси-сервер, обслуживающий все модули (публичные и частные), обеспечивает максимальный контроль для администраторов и требует минимальной настройки для отдельных разработчиков.
Чтобы настроить команду go
для использования такого сервера, установите следующие переменные среды, заменив https://proxy.corp.example.com
на URL вашего прокси и corp.example.com
на префикс вашего модуля:
GOPROXY=https://proxy.corp.example.com
GONOSUMDB=corp.example.com
Настройка GOPROXY
указывает команде go
загружать модули только с https://proxy.corp.example.com
; команда go не будет подключаться к другим прокси-серверам или репозиториям контроля версий.
Настройка GONOSUMDB
указывает команде go
не использовать публичную базу данных контрольных сумм для аутентификации модулей с путями, начинающимися с corp.example.com
.
Прокси, работающий в этой конфигурации, скорее всего, потребует доступ на чтение к частным серверам контроля версий. Ему также потребуется доступ к общедоступному Интернету для загрузки новых версий общедоступных модулей.
Существует несколько реализаций серверов GOPROXY
, которые можно использовать таким образом. Минимальная реализация будет обслуживать файлы из каталога кэша модулей и использовать go mod download
(с соответствующей конфигурацией) для извлечения отсутствующих модулей.
Частный прокси-сервер, обслуживающий частные модули
Частный прокси-сервер может обслуживать частные модули, не обслуживая при этом общедоступные модули. Команду go
можно настроить так, чтобы она переключалась на общедоступные источники для модулей, которые недоступны на частном сервере.
Чтобы настроить команду go
для работы в таком режиме, установите следующие переменные среды, заменив https://proxy.corp.example.com
на URL прокси-сервера, а corp.example.com
на префикс модуля:
GOPROXY=https://proxy.corp.example.com,https://proxy.golang.org,direct
GONOSUMDB=corp.example.com
Настройка GOPROXY
указывает команде go сначала пытаться загрузить модули с https://proxy.corp.example.com
. Если этот сервер отвечает кодом 404 (Not Found) или 410 (Gone), команда go переходит к https://proxy.golang.org
, а затем к прямым подключениям к репозиториям.
Настройка GONOSUMDB
указывает команде go
не использовать общедоступную базу данных контрольных сумм для аутентификации модулей, пути к которым начинаются с corp.example.com
.
Обратите внимание, что прокси, используемый в этой конфигурации, может по-прежнему контролировать доступ к общедоступным модулям, даже если он их не обслуживает. Если прокси отвечает на запрос со статусом ошибки, отличным от 404 или 410, команда go не будет переходить к более поздним записям в списке GOPROXY
. Например, прокси может ответить 403 (Forbidden) для модуля с неподходящей лицензией или с известными уязвимостями безопасности.
Прямой доступ к частным модулям
Команду go
можно настроить так, чтобы она обходила общедоступные прокси-серверы и загружала частные модули напрямую с серверов контроля версий. Это полезно, когда запуск частного прокси-сервера невозможен.
Чтобы настроить команду go для работы в таком режиме, установите GOPRIVATE
, заменив corp.example.com
префиксом частного модуля:
GOPRIVATE=corp.example.com
В этой ситуации переменную GOPROXY
менять не нужно. По умолчанию она имеет значение https://proxy.golang.org,direct
, что указывает команде go
сначала пытаться загрузить модули с https://proxy.golang.org
, а затем перейти к прямому подключению, если этот прокси отвечает 404 (Not Found) или 410 (Gone).
Настройка GOPRIVATE
указывает команде go
не подключаться к прокси или базе данных контрольных сумм для модулей, начинающихся с corp.example.com
.
Для преобразования путей модулей в URL-адреса репозиториев по-прежнему может потребоваться внутренний HTTP-сервер. Например, когда команда go
загружает модуль corp.example.com/mod
, она отправляет запрос GET
на https://corp.example.com/mod?go-get=1
и ищет URL-адрес репозитория в ответе. Чтобы избежать этого требования, убедитесь, что каждый частный путь модуля имеет суффикс VCS
(например, .git
), обозначающий префикс корня репозитория. Например, когда команда go
загружает модуль corp.example.com/repo.git/mod
, она клонирует репозиторий Git
по адресу https://corp.example.com/repo.git
или ssh://corp.example.com/repo.git
без необходимости делать дополнительные запросы.
Разработчикам потребуется доступ на чтение к репозиториям, содержащим частные модули. Это можно настроить в глобальных файлах конфигурации VCS, таких как .gitconfig
. Лучше всего, если инструменты VCS
настроены так, чтобы не требовать интерактивных запросов аутентификации. По умолчанию при вызове Git
команда go
отключает интерактивные запросы, устанавливая GIT_TERMINAL_PROMPT=0
, но она учитывает явные настройки.
Передача учетных данных частным прокси-серверам
Команда go
поддерживает базовую аутентификацию HTTP при взаимодействии с прокси-серверами.
Учетные данные могут быть указаны в файле .netrc
. Например, файл .netrc
, содержащий приведенные ниже строки, настроит команду go
на подключение к машине proxy.corp.example.com
с указанным именем пользователя и паролем.
machine proxy.corp.example.com
login jrgopher
password hunter2
Расположение файла можно установить с помощью переменной среды NETRC
. Если NETRC
не установлена, команда go будет читать $HOME/.netrc
на UNIX-подобных платформах или %USERPROFILE%\_netrc
в Windows.
Поля в .netrc
разделены пробелами, табуляциями и символами новой строки. К сожалению, эти символы не могут использоваться в именах пользователей или паролях. Также обратите внимание, что имя машины не может быть полным URL-адресом, поэтому невозможно указать разные имена пользователей и пароли для разных путей на одной машине.
В качестве альтернативы учетные данные можно указать непосредственно в URL-адресах GOPROXY
. Например:
GOPROXY=https://jrgopher:hunter2@proxy.corp.example.com
Будьте осторожны при использовании этого подхода: переменные среды могут появляться в истории оболочки и в журналах.
Передача учетных данных в частные репозитории
Команда go
может загружать модуль непосредственно из репозитория системы контроля версий. Это необходимо для частных модулей, если не используется частный прокси. См. раздел Прямой доступ к частным модулям для настройки.
Команда go
запускает инструменты контроля версий, такие как git
, при прямой загрузке модулей. Эти инструменты выполняют собственную аутентификацию, поэтому вам может потребоваться настроить учетные данные в конфигурационном файле, специфичном для инструмента, например .gitconfig
.
Чтобы обеспечить бесперебойную работу, убедитесь, что команда go
использует правильный URL-адрес репозитория и что инструмент контроля версий не требует ввода пароля в интерактивном режиме. Команда go
предпочитает URL-адреса https://
другим схемам, таким как ssh://
, если схема не была указана при поиске URL-адреса репозитория. Специально для репозиториев GitHub
команда go
предполагает использование https://
.
Для большинства серверов вы можете настроить клиент на аутентификацию по HTTP
. Например, GitHub
поддерживает использование личных токенов доступа OAuth
в качестве паролей HTTP
. Вы можете хранить пароли HTTP
в файле .netrc
, как при передаче учетных данных частным прокси-серверам.
В качестве альтернативы можно переписать URL-адреса https://
в другую схему. Например, в .gitconfig
:
[url «git@github.com:»]
insteadOf = https://github.com/
Для получения дополнительной информации см. Почему «go get
» использует HTTPS при клонировании репозитория?
Конфиденциальность
Команда go
может загружать модули и метаданные с прокси-серверов модулей и систем контроля версий. Переменная окружения GOPROXY
контролирует, какие серверы используются. Переменные окружения GOPRIVATE
и GONOPROXY
контролируют, какие модули загружаются с прокси-серверов.
Значение по умолчанию для GOPROXY
:
https://proxy.golang.org,direct
С этой настройкой, когда команда go
загружает модуль или метаданные модуля, она сначала отправляет запрос на proxy.golang.org
, общедоступный прокси-сервер модулей, управляемый Google
(политика конфиденциальности). См. протокол GOPROXY
для получения подробной информации о том, какая информация отправляется в каждом запросе. Команда go
не передает личную информацию, но передает полный путь к запрашиваемому модулю. Если прокси отвечает со статусом 404 (Not Found) или 410 (Gone), команда go
попытается подключиться напрямую к системе контроля версий, предоставляющей модуль. Подробности см. в разделе Системы контроля версий.
Переменные среды GOPRIVATE
или GONOPROXY
могут быть установлены в виде списков шаблонов glob
, соответствующих префиксам модулей, которые являются частными и не должны запрашиваться у какого-либо прокси. Например:
GOPRIVATE=*.corp.example.com,*.research.example.com
GOPRIVATE
просто действует как значение по умолчанию для GONOPROXY
и GONOSUMDB
, поэтому нет необходимости устанавливать GONOPROXY
, если GONOSUMDB
не должен иметь другое значение. Когда путь к модулю соответствует GONOPROXY
, команда go игнорирует GOPROXY для этого модуля и извлекает его напрямую из репозитория системы контроля версий. Это полезно, когда ни один прокси не обслуживает частные модули. См. Прямой доступ к частным модулям.
Если есть доверенный прокси, обслуживающий все модули, то GONOPROXY
не следует устанавливать. Например, если GOPROXY
установлен на один источник, команда go не будет загружать модули из других источников. В этой ситуации GONOSUMDB все равно следует установить.
GOPROXY=https://proxy.corp.example.com
GONOSUMDB=*.corp.example.com,*.research.example.com
Если есть доверенный прокси-сервер, обслуживающий только частные модули, GONOPROXY
не следует устанавливать, но необходимо убедиться, что прокси-сервер отвечает с правильными кодами статуса. Рассмотрим, например, следующую конфигурацию:
GOPROXY=https://proxy.corp.example.com,https://proxy.golang.org
GONOSUMDB=*.corp.example.com,*.research.example.com
Предположим, что из-за опечатки разработчик пытается загрузить модуль, которого не существует.
go mod download corp.example.com/secret-product/typo@latest
Команда go
сначала запрашивает этот модуль у proxy.corp.example.com
. Если этот прокси отвечает кодом 404 (Not Found) или 410 (Gone), команда go переходит к proxy.golang.org
, передавая путь secret-product в URL-адресе запроса. Если частный прокси отвечает любым другим кодом ошибки, команда go выводит ошибку и не переходит к другим источникам.
В дополнение к прокси, команда go
может подключаться к базе данных контрольных сумм для проверки криптографических хэшей модулей, не указанных в go.sum
. Переменная среды GOSUMDB
устанавливает имя, URL и открытый ключ базы данных контрольных сумм. По умолчанию GOSUMDB
имеет значение sum.golang.org
, открытая база данных контрольных сумм, управляемая Google
(политика конфиденциальности). См. База данных контрольных сумм для получения подробной информации о том, что передается с каждым запросом. Как и в случае с прокси-серверами, команда go не передает личную информацию, но передает полный путь к запрашиваемому модулю, а база данных контрольных сумм не может вычислять контрольные суммы для непубличных модулей.
Переменная среды GONOSUMDB
может быть установлена на шаблоны, указывающие, какие модули являются частными и не должны запрашиваться из базы данных контрольных сумм. GOPRIVATE
действует как значение по умолчанию для GONOSUMDB
и GONOPROXY
, поэтому нет необходимости устанавливать GONOSUMDB
, если GONOPROXY
не должен иметь другое значение.
Прокси может зеркалировать базу данных контрольных сумм. Если прокси в GOPROXY делает это, команда go не будет подключаться к базе данных контрольных сумм напрямую.
GOSUMDB
может быть установлена в off
, чтобы полностью отключить использование базы данных контрольных сумм. С этой настройкой команда go
не будет аутентифицировать загруженные модули, если они уже не находятся в go.sum
. См. Аутентификация модулей.
Кэш модулей
Кэш модулей — это каталог, в котором команда go
хранит загруженные файлы модулей. Кэш модулей отличается от кэша сборки, который содержит скомпилированные пакеты и другие артефакты сборки.
По умолчанию кэш модулей находится в каталоге $GOPATH/pkg/mod
. Чтобы использовать другое местоположение, установите переменную среды GOMODCACHE
.
Кэш модулей не имеет максимального размера, и команда go
не удаляет его содержимое автоматически.
Кэш может использоваться совместно несколькими проектами Go
, разрабатываемыми на одном компьютере. Команда go
будет использовать один и тот же кэш независимо от местоположения главного модуля. Несколько экземпляров команды go могут безопасно одновременно обращаться к одному и тому же кэшу модулей.
Команда go
создает исходные файлы модулей и каталоги в кэше с правами только для чтения, чтобы предотвратить случайные изменения модулей после их загрузки. Это имеет нежелательный побочный эффект, затрудняющий удаление кэша с помощью таких команд, как rm -rf
. Вместо этого кэш можно удалить с помощью go clean -modcache
.
В качестве альтернативы, при использовании флага -modcacherw
команда go
создаст новые каталоги с правами на чтение и запись. Это увеличивает риск изменения файлов в кэше модулей редакторами, тестами и другими программами.
Команда go mod verify
может использоваться для обнаружения изменений в зависимостях основного модуля. Она сканирует извлеченное содержимое каждой зависимости модуля и подтверждает, что оно соответствует ожидаемому хешу в go.sum
.
В таблице ниже объясняется назначение большинства файлов в кэше модулей. Некоторые временные файлы (файлы блокировки, временные каталоги) опущены. Для каждого пути $module
— это путь к модулю, а $version
— версия. Пути, заканчивающиеся косыми чертами (/
), являются каталогами. Заглавные буквы в путях к модулям и версиях экранируются с помощью восклицательных знаков (Azure экранируется как !azure), чтобы избежать конфликтов в файловых системах, нечувствительных к регистру.
Путь | Описание |
---|---|
$module@$version/ | Каталог, содержащий извлеченное содержимое файла .zip модуля. Он служит корневым каталогом для загруженного модуля. Он не будет содержать файл go.mod , если исходный модуль не имел такого файла. |
cache/download/ | Каталог, содержащий файлы, загруженные с прокси-серверов модулей, и файлы, полученные из систем контроля версий. Структура этого каталога соответствует протоколу GOPROXY , поэтому этот каталог может использоваться в качестве прокси-сервера при обслуживании HTTP-файловым сервером или при обращении по URL-адресу file:// . |
cache/download/$module/@v/list | Список известных версий (см. протокол GOPROXY ). Он может меняться со временем, поэтому команда go обычно загружает новую копию вместо повторного использования этого файла. |
cache/download/$module/@v/$version.info | JSON -метаданные о версии. (см. протокол GOPROXY ). Это может измениться со временем, поэтому команда go обычно загружает новую копию вместо повторного использования этого файла. |
cache/download/$module/@v/$version.mod | Файл go.mod для этой версии (см. протокол GOPROXY ). Если исходный модуль не имел файла go.mod , это синтезированный файл без требований. |
cache/download/$module/@v/$version.zip | Сжатое содержимое модуля (см. протокол GOPROXY и zip -файлы модулей). |
cache/download/$module/@v/$version.ziphash | Криптографический хеш файлов в файле .zip . Обратите внимание, что сам файл .zip не хешируется, поэтому порядок файлов, сжатие, выравнивание и метаданные не влияют на хеш. При использовании модуля команда go проверяет, что этот хеш соответствует соответствующей строке в go.sum . Команда go mod verify проверяет, что хеши файлов .zip модуля и извлеченных каталогов соответствуют этим файлам. |
cache/download/sumdb/ | Каталог, содержащий файлы, загруженные из базы данных контрольных сумм (обычно sum.golang.org ). |
cache/vcs/ | Содержит клонированные репозитории контроля версий для модулей, полученных непосредственно из их источников. Имена каталогов представляют собой хэши в шестнадцатеричном кодировании, полученные из типа репозитория и URL. Репозитории оптимизированы по размеру на диске. Например, клонированные репозитории Git являются «голыми» и «неглубокими», когда это возможно. |
Аутентификация модулей
Когда команда go
загружает zip
-файл модуля или файл go.mod
в кэш модулей, она вычисляет криптографический хеш и сравнивает его с известным значением, чтобы убедиться, что файл не изменился с момента его первой загрузки. Команда go
сообщает об ошибке безопасности, если загруженный файл не имеет правильного хеша.
Для файлов go.mod
команда go
вычисляет хеш из содержимого файла. Для zip
-файлов модулей команда go
вычисляет хеш из имен и содержимого файлов в архиве в детерминированном порядке. На хеш не влияют порядок файлов, сжатие, выравнивание и другие метаданные. См. golang.org/x/mod/sumdb/dirhash
для получения подробной информации о реализации хеша.
Команда go
сравнивает каждый хеш с соответствующей строкой в файле go.sum
основного модуля. Если хеш отличается от хеша в go.sum
, команда go
сообщает об ошибке безопасности и удаляет загруженный файл, не добавляя его в кэш модуля.
Если файл go.sum
отсутствует или не содержит хэш для загруженного файла, команда go
может проверить хэш с помощью базы данных контрольных сумм, глобального источника хэшей для общедоступных модулей. После проверки хеша команда go добавляет его в go.sum
и добавляет загруженный файл в кэш модулей. Если модуль является частным (соответствует переменным окружения GOPRIVATE
или GONOSUMDB
) или если база данных контрольных сумм отключена (путем установки GOSUMDB=off
), команда go
принимает хеш и добавляет файл в кэш модулей без проверки.
Кэш модулей обычно используется всеми проектами Go
в системе, и каждый модуль может иметь свой собственный файл go.sum
с потенциально разными хэшами. Чтобы избежать необходимости доверять другим модулям, команда go
проверяет хэши с помощью go.sum
основного модуля при каждом доступе к файлу в кэше модулей. Вычисление хэшей zip
-файлов требует больших затрат, поэтому команда go
проверяет заранее вычисленные хэши, хранящиеся вместе с zip
-файлами, вместо повторного хеширования файлов. Команда go mod verify
может использоваться для проверки того, что zip
-файлы и извлеченные каталоги не были изменены с момента их добавления в кэш модулей.
Файлы go.sum
Модуль может иметь текстовый файл с именем go.sum
в своем корневом каталоге, наряду с файлом go.mod
. Файл go.sum
содержит криптографические хэши прямых и косвенных зависимостей модуля. Когда команда go
загружает файл .mod
или .zip
модуля в кэш модулей, она вычисляет хеш и проверяет, что он совпадает с соответствующим хешем в файле go.sum
основного модуля. go.sum
может быть пустым или отсутствовать, если модуль не имеет зависимостей или если все зависимости заменены локальными каталогами с помощью директив replace
.
Каждая строка в go.sum
имеет три поля, разделенных пробелами: путь к модулю, версия (возможно, заканчивающаяся на /go.mod
) и хеш.
- Путь к модулю — это имя модуля, к которому принадлежит хеш.
- Версия — это версия модуля, к которому принадлежит хеш. Если версия заканчивается на
/go.mod
, хеш относится только к файлуgo.mod
модуля; в противном случае хеш относится к файлам в файле.zip
модуля. - Столбец хеша состоит из имени алгоритма (например, h1) и криптографического хеша, закодированного в base64, разделенных двоеточием (:). В настоящее время SHA-256 (h1) является единственным поддерживаемым алгоритмом хеширования. Если в будущем будет обнаружена уязвимость в SHA-256, будет добавлена поддержка другого алгоритма (с именем h2 и так далее).
Файл go.sum
может содержать хэши для нескольких версий модуля. Команде go
может потребоваться загрузить файлы go.mod
из нескольких версий зависимости, чтобы выполнить выбор минимальной версии. go.sum
также может содержать хэши для версий модулей, которые больше не нужны (например, после обновления). go mod tidy
добавит отсутствующие хэши и удалит ненужные хэши из go.sum
.
База данных контрольных сумм
База данных контрольных сумм является глобальным источником строк go.sum
. Команда go
может использовать ее во многих ситуациях для обнаружения некорректного поведения прокси-серверов или исходных серверов.
База данных контрольных сумм обеспечивает глобальную согласованность и надежность всех общедоступных версий модулей. Она делает возможным использование ненадежных прокси-серверов, поскольку они не могут предоставлять неверный код, который останется незамеченным. Она также гарантирует, что биты, связанные с конкретной версией, не изменятся со дня на день, даже если автор модуля впоследствии изменит теги в своем репозитории.
База данных контрольных сумм обслуживается sum.golang.org
, который управляется Google
. Это прозрачный журнал (или «дерево Меркла») хэшей строк go.sum
, который поддерживается Trillian
. Главное преимущество дерева Меркла заключается в том, что независимые аудиторы могут проверить, что оно не было подделано, поэтому оно более надежно, чем простая база данных.
Команда go
взаимодействует с базой данных контрольных сумм, используя протокол, первоначально описанный в предложении: «Обеспечение безопасности экосистемы публичных модулей Go».
В таблице ниже указаны запросы, на которые должна отвечать база данных контрольных сумм. Для каждого пути $base
— это часть URL-адреса базы данных контрольных сумм, $module
— путь к модулю, а $version
— версия. Например, если URL базы данных контрольных сумм — https://sum.golang.org
, а клиент запрашивает запись для модуля golang.org/x/text
версии v0.3.2
, клиент отправит запрос GET
на https://sum.golang.org/lookup/golang.org/x/text@v0.3.2
.
Чтобы избежать неоднозначности при обслуживании из файловых систем, нечувствительных к регистру, элементы $module
и $version
кодируются с учетом регистра, заменяя каждую заглавную букву восклицательным знаком, за которым следует соответствующая строчная буква. Это позволяет хранить на диске модули example.com/M
и example.com/m
, поскольку первый кодируется как example.com/!m
.
Части пути, заключенные в квадратные скобки, такие как [.p/$W]
, обозначают необязательные значения.
Путь | Описание |
---|---|
$base/latest | Возвращает подписанное, закодированное описание дерева для последнего журнала. Это подписанное описание имеет форму примечания, которое представляет собой текст, подписанный одним или несколькими ключами сервера и который можно проверить с помощью открытого ключа сервера. Описание дерева содержит размер дерева и хэш вершины дерева при данном размере. Это кодирование описано в golang.org/x/mod/sumdb/tlog#FormatTree . |
$base/lookup/$module@$version | Возвращает номер записи журнала для записи о $module в $version , за которым следуют данные для записи (то есть строки go.sum для $module в $version ) и подписанное, закодированное описание дерева, которое содержит запись. |
$base/tile/$H/$L/$K[.p/$W] | Возвращает блоку журнала, который представляет собой набор хешей, составляющих раздел журнала. Каждый блок определяется в двумерных координатах на уровне блока $L , $K -м слева, с высотой блока $H . Необязательный суффикс .p/$W указывает на частичную плитку журнала, содержащую только $W хешей. Клиенты должны перейти к извлечению полной плитки, если частичная плитка не найдена. |
$base/tile/$H/data/$K[.p/$W] | Возвращает данные записи для листьевых хешей в /tile/$H/0/$K[.p/$W] (с буквальным элементом пути данных). |
Если команда go
обращается к базе данных контрольных сумм, то первым шагом является извлечение данных записи через конечную точку /lookup
. Если версия модуля еще не записана в журнале, база данных контрольных сумм попытается получить ее с исходного сервера перед ответом. Эти данные /lookup
предоставляют сумму для этой версии модуля, а также ее положение в журнале, что информирует клиента о том, какие плитки следует загрузить для выполнения проверок. Команда go
выполняет проверки «включения» (наличие определенной записи в журнале) и «согласованности» (отсутствие подделки дерева) перед добавлением новых строк go.sum
в файл go.sum
основного модуля. Важно, чтобы данные из /lookup
никогда не использовались без предварительной аутентификации по подписанному хешу дерева и аутентификации подписанного хеша дерева по временной шкале подписанных хешей дерева клиента.
Подписанные хеши дерева и новые плитки, обслуживаемые базой данных контрольных сумм, хранятся в кэше модуля, поэтому команде go
нужно загружать только отсутствующие плитки.
Команде go
не нужно напрямую подключаться к базе данных контрольных сумм. Она может запрашивать суммы модулей через прокси-сервер модулей, который зеркалирует базу данных контрольных сумм и поддерживает вышеуказанный протокол. Это может быть особенно полезно для частных корпоративных прокси-серверов, которые блокируют запросы за пределами организации.
Переменная среды GOSUMDB
определяет имя базы данных контрольных сумм, которую следует использовать, и, опционально, ее открытый ключ и URL, как в примере:
GOSUMDB="sum.golang.org"
GOSUMDB="sum.golang.org+<publickey>"
GOSUMDB="sum.golang.org+<publickey> https://sum.golang.org"
Команда go
знает открытый ключ sum.golang.org
, а также то, что имя sum.golang.google.cn
(доступно на территории материкового Китая) соединяет с базой данных контрольных сумм sum.golang.org
; использование любой другой базы данных требует явного указания открытого ключа. URL по умолчанию https://
, за которым следует имя базы данных.
GOSUMDB
по умолчанию указывает на sum.golang.org
, базу данных контрольных сумм Go, управляемую Google. Политику конфиденциальности сервиса смотрите на https://sum.golang.org/privacy
.
Если для GOSUMDB
установлено значение off
, или если go get
вызывается с флагом -insecure
, база данных контрольных сумм не проверяется, и все нераспознанные модули принимаются, ценой отказа от гарантии безопасности проверенных повторяющихся загрузок для всех модулей. Лучший способ обойти базу данных контрольных сумм для определенных модулей - использовать переменные окружения GOPRIVATE
или GONOSUMDB
. Подробности см. в разделе Приватные модули.
Команда go env -w
может быть использована для установки этих переменных для последующих вызовов команды go
.
Переменные окружения
Поведение модуля в команде go
может быть настроено с помощью переменных окружения, перечисленных ниже. В этот список включены только переменные окружения, связанные с модулем. Список всех переменных окружения, распознаваемых командой go
, см. в go help environment
.
- GO111MODULE
-
Управляет тем, будет ли команда go работать в режиме с поддержкой модулей или в режиме
GOPATH
. Поддерживаются три значения:- off: команда go игнорирует файлы
go.mod
и работает в режимеGOPATH
. - on (или unset): команда
go
работает в режиме с поддержкой модулей, даже если файлgo.mod
отсутствует. - auto: команда
go
работает в режиме с поддержкой модулей, если файлgo.mod
присутствует в текущем каталоге или любом родительском каталоге. В Go 1.15 и ниже это было значением по умолчанию.
Дополнительные сведения см. в разделе Команды с поддержкой модулей.
- off: команда go игнорирует файлы
- GOMODCACHE
-
Каталог, в котором команда
go
будет хранить загруженные модули и связанные файлы. Подробные сведения о структуре этого каталога см. в разделе Кэш модулей.Если
GOMODCACHE
не установлен, по умолчанию используется$GOPATH/pkg/mod
.
- GOINSECURE
-
Разделенный запятыми список шаблонов
glob
(в синтаксисеpath.Match Go
) префиксов путей модулей, которые всегда могут быть загружены небезопасным способом. Применяется только к зависимостям, которые загружаются напрямую.В отличие от флага
-insecure
вgo get
,GOINSECURE
не отключает проверку базы данных контрольных сумм модулей. Для этого можно использоватьGOPRIVATE
илиGONOSUMDB
.
- GONOPROXY
-
Разделенный запятыми список шаблонов
glob
(в синтаксисеpath.Match Go
) префиксов путей модулей, которые всегда должны загружаться напрямую из репозиториев контроля версий, а не из прокси-серверов модулей.Если
GONOPROXY
не установлен, по умолчанию используетсяGOPRIVATE
. См. раздел «Конфиденциальность».
- GONOSUMDB
-
Разделенный запятыми список шаблонов
glob
(в синтаксисеpath.Match Go
) префиксов путей модулей, для которыхgo
не должен проверять контрольные суммы с помощью базы данных контрольных сумм.Если
GONOSUMDB
не установлен, по умолчанию используетсяGOPRIVATE
. См. раздел «Конфиденциальность».
- GOPATH
-
В режиме
GOPATH
переменнаяGOPATH
представляет собой список каталогов, которые могут содержать кодGo
.В режиме с поддержкой модулей кэш модулей хранится в подкаталоге
pkg/mod
первого каталогаGOPATH
. Исходный код модулей, не входящих в кэш, может храниться в любом каталоге.Если
GOPATH
не задан, по умолчанию используется подкаталогgo
в домашнем каталоге пользователя.
- GOPRIVATE
-
Разделенный запятыми список шаблонов
glob
(в синтаксисеpath.Match Go
) префиксов путей модулей, которые должны считаться частными.GOPRIVATE
является значением по умолчанию дляGONOPROXY
иGONOSUMDB
. См. раздел «Конфиденциальность».GOPRIVATE
также определяет, считается ли модуль частным дляGOVCS
.
- GOPROXY
-
Список URL-адресов прокси-серверов модулей, разделенных запятыми (
,
) или вертикальными чертами (|
). Когда командаgo
ищет информацию о модуле, она обращается к каждому прокси-серверу в списке по порядку, пока не получит успешный ответ или терминальную ошибку. Прокси-сервер может ответить статусом 404 (Not Found) или 410 (Gone), чтобы указать, что модуль недоступен на этом сервере.Поведение команды
go
при ошибке определяется разделителями между URL-адресами. Если за URL-адресом прокси следует запятая, команда go переходит к следующему URL-адресу после ошибки 404 или 410; все другие ошибки считаются терминальными. Если за URL-адресом прокси следует вертикальная черта, команда go переходит к следующему источнику после любой ошибки, включая ошибки, не связанные с HTTP, такие как таймауты.URL-адреса
GOPROXY
могут иметь схемыhttps
,http
илиfile
. Если URL-адрес не имеет схемы, предполагается, что он имеет схемуhttps
. Кэш модулей может использоваться непосредственно в качестве прокси-файла:GOPROXY=file://$(go env GOMODCACHE)/cache/download
Вместо URL-адресов прокси могут использоваться два ключевых слова:
- off: запрещает загрузку модулей из любого источника.
- direct: загрузка напрямую из репозиториев контроля версий вместо использования прокси-сервера модулей.
По умолчанию
GOPROXY
имеет значениеhttps://proxy.golang.org,direct
. При такой конфигурации команда go сначала связывается с зеркалом модулей Go, управляемым Google, а затем переходит к прямому подключению, если зеркало не имеет модуля. Политику конфиденциальности зеркала см. на страницеhttps://proxy.golang.org/privacy
. Переменные средыGOPRIVATE
иGONOPROXY
могут быть установлены, чтобы предотвратить загрузку определенных модулей с помощью прокси. См. раздел «Конфиденциальность» для получения информации о настройке частного прокси.См. разделы «Прокси модулей» и «Преобразование пакета в модуль» для получения дополнительной информации об использовании прокси.
- GOSUMDB
-
Определяет имя базы данных контрольных сумм, которую следует использовать, а также, по желанию, ее открытый ключ и URL. Например:
GOSUMDB="sum.golang.org" GOSUMDB="sum.golang.org+<publickey>" GOSUMDB="sum.golang.org+<publickey> https://sum.golang.org"
Команда go знает открытый ключ
sum.golang.org
, а также то, что имяsum.golang.google.cn
(доступное на территории Китая) подключается к базе данныхsum.golang.org
; для использования любой другой базы данных необходимо явно указать открытый ключ. По умолчанию URL-адрес имеет видhttps://
, за которым следует имя базы данных.По умолчанию
GOSUMDB
имеет значениеsum.golang.org
, базу данных контрольных сумм Go, управляемую Google. См.https://sum.golang.org/privacy
для ознакомления с политикой конфиденциальности службы.Если
GOSUMDB
установлен в положение«off»
или еслиgo get
вызывается с флагом-insecure
, база данных контрольных сумм не используется, и все нераспознанные модули принимаются, что приводит к потере гарантии безопасности проверенных повторяемых загрузок для всех модулей. Лучший способ обойти базу данных контрольных сумм для определенных модулей — использовать переменные средыGOPRIVATE
илиGONOSUMDB
.Дополнительную информацию см. в разделах «Аутентификация модулей» и «Конфиденциальность».
- GOVCS
-
Управляет набором инструментов контроля версий, которые команда
go
может использовать для загрузки общедоступных и частных модулей (определяемых по тому, соответствуют ли их пути шаблону вGOPRIVATE
) или других модулей, соответствующих шаблонуglob
.Если
GOVCS
не установлен или если модуль не соответствует ни одному шаблону вGOVCS
, команда go может использоватьgit
иhg
для публичного модуля или любой известный инструмент контроля версий для частного модуля. Конкретно, команда go действует так, как если быGOVCS
был установлен на:public:git|hg,private:all
См. Управление инструментами контроля версий с помощью
GOVCS
для полного объяснения.
- GOWORK
-
Переменная окружения
GOWORK
указывает командеgo
перейти в режим рабочего пространства, используя предоставленный файлgo.work
для определения рабочего пространства. ЕслиGOWORK
установлен вoff
, режим рабочего пространства отключается. Это можно использовать для запуска командыgo
в режиме одного модуля: например,GOWORK=off go build .
собирает пакет.
в режиме одного модуля. ЕслиGOWORK
пуста, командаgo
будет искать файлgo.work
, как описано в разделе Рабочие пространства.
Глоссарий
Ограничение сборки: условие, которое определяет, будет ли использоваться исходный файл Go при компиляции пакета. Ограничения сборки могут быть выражены с помощью суффиксов имен файлов (например, foo_linux_amd64.go) или с помощью комментариев об ограничениях сборки (например, // +build linux,amd64). См. Ограничения сборки.
Список сборки: список версий модулей, которые будут использоваться для команды сборки, такой как go build, go list или go test. Список сборки определяется из файла go.mod основного модуля и файлов go.mod в транзитивно требуемых модулях с использованием минимального выбора версии. Список сборки содержит версии для всех модулей в графе модулей, а не только для тех, которые относятся к конкретной команде.
каноническая версия: правильно отформатированная версия без суффикса метаданных сборки, кроме +incompatible. Например, v1.2.3 является канонической версией, а v1.2.3+meta — нет.
текущий модуль: синоним основного модуля.
Устаревший модуль: модуль, который больше не поддерживается его авторами (хотя основные версии считаются отдельными модулями для этой цели). Устаревший модуль помечается комментарием об устаревании в последней версии его файла go.mod.
Прямая зависимость: пакет, путь к которому появляется в декларации импорта в исходном файле .go для пакета или теста в основном модуле, или модуль, содержащий такой пакет. (Сравните с косвенной зависимостью.)
Прямой режим: настройка переменных среды, которая заставляет команду go загружать модуль напрямую из системы контроля версий, а не через прокси-сервер модулей. GOPROXY=direct делает это для всех модулей. GOPRIVATE и GONOPROXY делают это для модулей, соответствующих списку шаблонов.
Файл go.mod: файл, который определяет путь к модулю, требования и другие метаданные. Появляется в корневом каталоге модуля. См. раздел о файлах go.mod.
Файл go.work: файл, который определяет набор модулей, которые будут использоваться в рабочей области. См. раздел о файлах go.work.
Путь импорта: строка, используемая для импорта пакета в исходном файле Go. Синоним пути к пакету.
Косвенная зависимость: пакет, транзитивно импортируемый пакетом или тестом в главном модуле, но путь к которому не появляется ни в одной декларации импорта в главном модуле; или модуль, который появляется в графе модулей, но не предоставляет никаких пакетов, напрямую импортируемых главным модулем. (Сравните с прямой зависимостью.)
отложенная загрузка модулей: изменение в Go 1.17, которое позволяет избежать загрузки графа модулей для команд, которые в этом не нуждаются, в модулях, которые указывают go 1.17 или выше. См. Отложенная загрузка модулей.
главный модуль: модуль, в котором вызывается команда go. Главный модуль определяется файлом go.mod в текущем каталоге или родительском каталоге. См. Модули, пакеты и версии.
Основная версия: первое число в семантической версии (1 в v1.2.3). В выпуске с несовместимыми изменениями основная версия должна быть увеличена, а второстепенная версия и патч-версия должны быть установлены на 0. Семантические версии с основной версией 0 считаются нестабильными.
подкаталог основной версии: подкаталог в репозитории контроля версий, соответствующий суффиксу основной версии модуля, в котором может быть определен модуль. Например, модуль example.com/mod/v2 в репозитории с корневым путем example.com/mod может быть определен в корневом каталоге репозитория или в подкаталоге основной версии v2. См. Каталоги модулей в репозитории.
суффикс основной версии: суффикс пути модуля, соответствующий номеру основной версии. Например, /v2 в example.com/mod/v2. Суффиксы основной версии требуются в v2.0.0 и более поздних версиях и не допускаются в более ранних версиях. См. раздел «Суффиксы основной версии».
Выбор минимальной версии (MVS): алгоритм, используемый для определения версий всех модулей, которые будут использоваться в сборке. Подробности см. в разделе «Выбор минимальной версии».
Второстепенная версия: второе число в семантической версии (2 в v1.2.3). В выпуске с новой, обратно совместимой функциональностью второстепенная версия должна быть увеличена, а патч-версия должна быть установлена на 0.
Модуль: набор пакетов, которые выпускаются, версионируются и распространяются вместе.
Кэш модулей: локальный каталог, в котором хранятся загруженные модули, расположенный в GOPATH/pkg/mod. См. Кэш модулей.
Граф модулей: ориентированный граф требований модулей, корнем которого является главный модуль. Каждая вершина в графе — это модуль; каждая ребро — это версия из оператора require в файле go.mod (с учетом операторов replace и exclude в файле go.mod главного модуля).
Обрезка графа модулей: изменение в Go 1.17, которое уменьшает размер графа модулей за счет исключения транзитивных зависимостей модулей, которые указывают go 1.17 или выше. См. Обрезка графа модулей.
Путь модуля: путь, который идентифицирует модуль и действует как префикс для путей импорта пакетов внутри модуля. Например, «golang.org/x/net».
Прокси модуля: веб-сервер, который реализует протокол GOPROXY. Команда go загружает информацию о версии, файлы go.mod и zip-файлы модулей с прокси модулей.
Корневой каталог модуля: каталог, который содержит файл go.mod, определяющий модуль.
Подкаталог модуля: часть пути к модулю после корневого пути репозитория, которая указывает подкаталог, в котором определен модуль. Если подкаталог модуля не пустой, он также является префиксом для семантических тегов версии. Подкаталог модуля не включает суффикс основной версии, если таковой имеется, даже если модуль находится в подкаталоге основной версии. См. «Пути к модулям».
Пакет: набор исходных файлов в одном каталоге, которые компилируются вместе. См. раздел «Пакеты» в спецификации языка Go.
Путь к пакету: путь, который однозначно идентифицирует пакет. Путь к пакету — это путь к модулю, соединенный с подкаталогом внутри модуля. Например, «golang.org/x/net/html» — это путь к пакету в модуле «golang.org/x/net» в подкаталоге «html». Синоним пути импорта.
версия патча: третье число в семантической версии (3 в v1.2.3). В выпуске без изменений в публичном интерфейсе модуля версия патча должна быть увеличена.
Предварительная версия: версия с тире, за которым следует ряд идентификаторов, разделенных точками, непосредственно после патч-версии, например, v1.2.3-beta4. Предварительные версии считаются нестабильными и не предполагают совместимости с другими версиями. Предварительная версия сортируется перед соответствующей релизной версией: v1.2.3-pre идет перед v1.2.3. См. также релизная версия.
Псевдоверсия: версия, которая кодирует идентификатор ревизии (например, хэш Git commit) и временную метку из системы контроля версий. Например, v0.0.0-20191109021931-daa7c04131f5. Используется для совместимости с репозиториями, не являющимися модулями, и в других ситуациях, когда версия с тегом недоступна.
релизная версия: версия без суффикса предварительной версии. Например, v1.2.3, а не v1.2.3-pre. См. также предварительная версия.
корневой путь репозитория: часть пути модуля, которая соответствует корневому каталогу репозитория системы контроля версий. См. Пути модулей.
Отзывная версия: версия, на которую не следует полагаться, либо потому что она была опубликована преждевременно, либо потому что после ее публикации была обнаружена серьезная проблема. См. директиву retract.
Семантическая метка версии: метка в репозитории контроля версий, которая сопоставляет версию с конкретной ревизией. См. Сопоставление версий с коммитами.
выбранная версия: версия данного модуля, выбранная с помощью минимального выбора версии. Выбранная версия — это самая высокая версия для пути модуля, найденная в графе модулей.
каталог поставщика: каталог с именем vendor, содержащий пакеты из других модулей, необходимые для сборки пакетов в основном модуле. Обслуживается с помощью go mod vendor. См. раздел «Поставщики».
версия: идентификатор неизменяемого моментального снимка модуля, записываемый в виде буквы v, за которой следует семантическая версия. См. раздел «Версии».
рабочая область: набор модулей на диске, которые используются в качестве основных модулей при выполнении минимального выбора версии (MVS). См. раздел «Рабочие области».