Управление зависимостями

Когда ваш код использует внешние пакеты, эти пакеты (распространяемые как модули) становятся зависимостями. Со временем может потребоваться обновить их или заменить. Go предоставляет инструменты управления зависимостями, которые помогают поддерживать безопасность ваших Go-приложений при включении внешних зависимостей.

В этой статье описывается, как выполнять задачи по управлению зависимостями, которые вы добавляете в свой код. Большинство этих задач можно выполнять с помощью инструментов Go. Также описываются несколько других задач, связанных с зависимостями, которые могут оказаться полезными.

См. также

  • Если вы новичок в работе с зависимостями как с модулями, ознакомьтесь с руководством по началу работы для краткого введения.
  • Использование команды go для управления зависимостями помогает обеспечить соответствие ваших требований и корректность содержимого файла go.mod. Справочник по командам см. в разделе Команда go. Справку по команде можно получить из командной строки, введя go help имя-команды, например, go help mod tidy.
  • Команды Go, используемые для внесения изменений в зависимости, редактируют файл go.mod. Для получения информации о содержимом файла см. Справочник по файлу go.mod.
  • Сделать ваш редактор или IDE осведомленными о Go-модулях может облегчить работу по их управлению. Подробнее о редакторах, поддерживающих Go, см. в разделе Плагины редакторов и IDE.
  • В этой статье не описывается, как разрабатывать, публиковать и версионировать модули для использования другими. Подробнее см. в разделе Разработка и публикация модулей.

Рабочий процесс использования и управления зависимостями

Вы можете получать и использовать полезные пакеты с помощью инструментов Go. На сайте pkg.go.dev можно искать пакеты, которые могут оказаться полезными, а затем использовать команду go для импорта этих пакетов в свой код для вызова их функций.

Ниже приведен список наиболее распространенных шагов управления зависимостями. Для получения дополнительной информации о каждом из них см. соответствующие разделы в этой статье.

  1. Найти полезные пакеты на сайте pkg.go.dev.
  2. Импортировать пакеты, которые вы хотите использовать в коде.
  3. Добавить свой код в модуль для отслеживания зависимостей (если он еще не находится в модуле). См. Включение отслеживания зависимостей
  4. Добавить внешние пакеты как зависимости, чтобы можно было управлять ими.
  5. Обновлять или понижать версии зависимостей по мере необходимости.

Управление зависимостями как модули

В языке Go зависимости управляются с помощью модулей, содержащих пакеты, которые вы импортируете. Этот процесс поддерживается следующими элементами:

  • Децентрализованной системой публикации модулей и получения их кода. Разработчики делают свои модули доступными для других разработчиков из собственного репозитория и публикуют их с номером версии.
  • Поисковой системой пакетов и браузером документации (pkg.go.dev), где можно найти модули. См. Поиск и импорт полезных пакетов.
  • Соглашением о нумерации версий модулей, которое помогает понять стабильность модуля и гарантии обратной совместимости. См. Нумерация версий модулей.
  • Инструментами Go, облегчающими управление зависимостями, включая получение исходного кода модуля, его обновление и т. д. См. соответствующие разделы этой темы.

Поиск и импорт полезных пакетов

Вы можете использовать pkg.go.dev для поиска пакетов с функциями, которые могут оказаться полезными.

Когда вы найдёте пакет, который хотите использовать в своём коде, найдите путь к пакету в верхней части страницы и нажмите кнопку «Copy path» (Скопировать путь), чтобы скопировать путь в буфер обмена. В своём коде вставьте путь в инструкцию импорта, как в следующем примере:

<code>import "rsc.io/quote"
</code>

После того как ваш код импортирует пакет, включите отслеживание зависимостей и получите код пакета для компиляции. Подробнее см. Включение отслеживания зависимостей в вашем коде и Добавление зависимости.

Включение отслеживания зависимостей в вашем коде

Чтобы отслеживать и управлять добавленными зависимостями, вы начинаете с размещения своего кода в собственном модуле. Это создаёт файл go.mod в корне дерева исходных кодов. Зависимости, которые вы добавляете, будут перечислены в этом файле.

Чтобы добавить свой код в собственный модуль, используйте команду go mod init. Например, из командной строки перейдите в корневую директорию вашего кода и выполните команду, как в следующем примере:

<code>$ go mod init example/mymodule
</code>

Аргумент команды go mod init — это путь к модулю. По возможности путь к модулю должен совпадать с местоположением репозитория вашего исходного кода.

Если вы пока не знаете окончательное место расположения модуля в репозитории, используйте безопасную замену. Это может быть имя домена, которым вы владеете, или другое имя, которым вы управляете (например, название вашей компании), а также путь, следующий за названием модуля или директорией исходного кода. Подробнее см. Назначение имени модулю.

По мере использования инструментов Go для управления зависимостями, сами инструменты обновляют файл go.mod, чтобы он содержал актуальный список зависимостей.

Когда вы добавляете зависимости, инструменты Go также создают файл go.sum, который содержит контрольные суммы модулей, от которых вы зависите. Go использует этот файл для проверки целостности загруженных файлов модулей, особенно когда другие разработчики работают над вашим проектом.

Включайте файлы go.mod и go.sum в ваш репозиторий вместе с кодом.

См. справочник по go.mod для получения дополнительной информации.

Именование модуля

Когда вы запускаете go mod init для создания модуля для отслеживания зависимостей, вы указываете путь модуля, который служит его именем. Путь модуля становится префиксом импортного пути для пакетов в модуле. Убедитесь, что вы указываете путь модуля, который не будет конфликтовать с путем другого модуля.

По крайней мере, путь модуля должен указывать на что-то, связанное с его происхождением, например, название компании или автора. Но путь также может быть более описательным, указывая, что делает модуль.

Путь модуля обычно имеет следующий формат:

<code><prefix>/<descriptive-text>
</code>
  • Префикс обычно представляет собой строку, частично описывающую модуль, например, строку, описывающую его происхождение. Это может быть:

    • Местоположение репозитория, где инструменты Go могут найти исходный код модуля (обязательно, если вы публикуете модуль).

      Например, это может быть github.com/<project-name>/.

      Используйте эту лучшую практику, если вы думаете, что можете опубликовать модуль для использования другими. Подробнее о публикации см. в разделе Разработка и публикация модулей.

    • Имя, которым вы управляете.

      Если вы не используете имя репозитория, убедитесь, что выбрали префикс, который вы уверены, что никто другой не будет использовать. Хорошим выбором будет название вашей компании. Избегайте распространённых терминов, таких как widgets, utilities или app.

  • Для описательного текста хорошим выбором будет название проекта. Помните, что имена пакетов несут большую часть веса в описании функциональности. Путь модуля создаёт пространство имён для этих имён пакетов.

Зарезервированные префиксы путей модулей

Go гарантирует, что следующие строки не будут использоваться в именах пакетов.

  • test – Вы можете использовать test как префикс пути модуля для модуля, код которого предназначен для локального тестирования функций в другом модуле.

    Используйте префикс пути test для модулей, созданных как часть теста. Например, ваш тест может сам запустить go mod init test, а затем настроить этот модуль каким-то образом, чтобы протестировать с помощью инструмента анализа исходного кода Go.

  • example – Используется как префикс пути модуля в некоторых документациях Go, например, в учебных пособиях, где вы создаёте модуль только для отслеживания зависимостей.

    Обратите внимание, что документация Go также использует example.com, чтобы показать, когда пример может быть опубликованным модулем.

После того как вы начнёте импортировать пакеты из опубликованного модуля, вы можете добавить этот модуль в качестве зависимости, используя команду go get.

Команда выполняет следующие действия:

  • При необходимости она добавляет директивы require в ваш файл go.mod для модулей, необходимых для сборки пакетов, указанных в командной строке. Директива require отслеживает минимальную версию модуля, от которой зависит ваш модуль. Подробнее см. в справочнике по go.mod.

  • При необходимости она загружает исходный код модуля, чтобы вы могли компилировать пакеты, зависящие от них. Загрузка модулей может происходить через прокси-сервер модулей, такой как proxy.golang.org, или напрямую из репозиториев системы контроля версий. Исходный код кэшируется локально.

    Вы можете указать место, откуда инструменты Go загружают модули. Подробнее см. в разделе Указание прокси-сервера модулей.

Ниже описаны несколько примеров.

  • Чтобы добавить все зависимости для пакета в вашем модуле, выполните команду, подобную приведённой ниже («.» обозначает пакет в текущем каталоге):

    <code>$ go get .
    </code>
  • Чтобы добавить конкретную зависимость, укажите путь к модулю в качестве аргумента команды.

    <code>$ go get example.com/theirmodule
    </code>

Команда также проверяет подлинность каждого загруженного модуля. Это гарантирует, что он не изменился с момента публикации. Если модуль был изменён с момента публикации — например, разработчик изменил содержимое коммита — инструменты Go выдадут ошибку безопасности. Эта проверка защищает вас от модулей, которые могли быть подделаны.

Получение конкретной версии зависимости

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

Вы можете захотеть сделать это, если:

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

Примеры использования команды go get:

  • Чтобы получить конкретную номерную версию, добавьте к пути модуля знак @, за которым следует нужная версия:

    <code>$ go get example.com/theirmodule@v1.3.4
    </code>
  • Чтобы получить последнюю версию, добавьте к пути модуля @latest:

    <code>$ go get example.com/theirmodule@latest
    </code>

Пример директивы require в файле go.mod (см. справочник по go.mod):

go.mod reference для получения дополнительной информации) демонстрирует, как указать конкретный номер версии:

<code>require example.com/theirmodule v1.3.4
</code>

Обнаружение доступных обновлений

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

Для получения дополнительной информации о команде go list см. go list -m.

Ниже приведены несколько примеров.

  • Вывести все модули, являющиеся зависимостями текущего модуля, вместе с последней доступной версией для каждого:

    <code>$ go list -m -u all
    </code>
  • Отобразить последнюю доступную версию для конкретного модуля:

    <code>$ go list -m -u example.com/theirmodule
    </code>

Обновление или понижение зависимости

Вы можете обновить или понизить версию модуля зависимости, используя инструменты Go для поиска доступных версий, а затем добавив другую версию в качестве зависимости.

  1. Для поиска новых версий используйте команду go list, как описано в разделе Обнаружение доступных обновлений.

  2. Чтобы добавить определённую версию в качестве зависимости, используйте команду go get, как описано в разделе Получение конкретной версии зависимости.

Синхронизация зависимостей вашего кода

Вы можете убедиться, что вы управляете зависимостями для всех импортированных вами пакетов, а также удаляете зависимости для пакетов, которые больше не импортируются.

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

Чтобы сохранить набор управляемых зависимостей в порядке, используйте команду go mod tidy. Эта команда, используя набор импортированных пакетов в вашем коде, изменяет файл go.mod, добавляя модули, которые необходимы, но отсутствуют. Также она удаляет неиспользуемые модули, которые не предоставляют никаких соответствующих пакетов.

Команда не имеет аргументов, кроме одного флага -v, который выводит информацию об удалённых модулях.

<code>$ go mod tidy
</code>

Разработка и тестирование с использованием неопубликованного кода модуля

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

Вы можете сделать это, когда:

  • Вы хотите внести свои изменения в код внешнего модуля, например, после того как скопировали (forked) и/или клонировали его. Например, вы можете захотеть подготовить исправление модуля, а затем отправить его в виде pull request разработчику модуля.
  • Вы создаёте новый модуль и ещё не опубликовали его, поэтому он недоступен в репозитории, к которому может обратиться команда go get.

Использование кода модуля из локального каталога

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

  • Разрабатываете собственный отдельный модуль и хотите протестировать его из текущего модуля.
  • Исправляете проблемы или добавляете функции в внешний модуль и хотите протестировать изменения из текущего модуля. (Обратите внимание, что вы также можете требовать внешний модуль из вашего собственного форка его репозитория. Подробнее см. в разделе Использование кода внешнего модуля из вашего собственного форка репозитория.)

Чтобы указать Go командам использовать локальную копию кода модуля, используйте директиву replace в вашем файле go.mod для замены пути модуля, указанного в директиве require. См. справочник по go.mod для получения дополнительной информации о директивах.

В следующем примере файла go.mod текущий модуль требует внешний модуль example.com/theirmodule, используя несуществующий номер версии (v0.0.0-unpublished), чтобы убедиться, что замена работает корректно. Директива replace заменяет исходный путь модуля на ../theirmodule, который представляет собой каталог на том же уровне, что и каталог текущего модуля.

<code>module example.com/mymodule

go 1.23.0

require example.com/theirmodule v0.0.0-unpublished

replace example.com/theirmodule v0.0.0-unpublished => ../theirmodule
</code>

При настройке пары require/replace используйте команды go mod edit и go get, чтобы убедиться, что требования, описанные в файле, остаются согласованными:

<code>$ go mod edit -replace=example.com/theirmodule@v0.0.0-unpublished=../theirmodule
$ go get example.com/theirmodule@v0.0.0-unpublished
</code>

Примечание: При использовании директивы replace, инструменты Go не проверяют подлинность внешних модулей, как описано в разделе Добавление зависимости.

Для получения дополнительной информации о номерах версий см. Нумерация версий модулей.

Использование кода внешнего модуля из вашего собственного форка репозитория

Когда вы создали форк репозитория внешнего модуля (например, чтобы исправить проблему в коде модуля или добавить функцию), вы можете заставить инструменты Go использовать ваш форк в качестве источника модуля. Это может быть полезно для тестирования изменений из вашего собственного кода. (Обратите внимание, что вы также можете требовать код модуля из каталога, который находится на локальном диске с модулем, который его требует. Подробнее см. в разделе Использование кода модуля из локального каталога.)

Вы делаете это, используя директиву replace в файле go.mod для замены исходного пути модуля на путь к форку в вашем репозитории. Это указывает инструментам Go использовать замещающий путь (расположение форка) при компиляции, например, позволяя при этом оставить инструкции import без изменений по сравнению с исходным путём модуля.

Более подробно о директиве replace см. в справочнике по файлу go.mod.

В следующем примере файла go.mod текущий модуль требует внешний модуль example.com/theirmodule. Директива replace заменяет оригинальный путь модуля на example.com/myfork/theirmodule, который является форком репозитория модуля.

<code>module example.com/mymodule

go 1.23.0

require example.com/theirmodule v1.2.3

replace example.com/theirmodule v1.2.3 => example.com/myfork/theirmodule v1.2.3-fixed
</code>

При настройке пары require/replace используйте команды инструментов Go, чтобы убедиться, что зависимости, описанные в файле, остаются согласованными. Используйте команду go list, чтобы получить версию, используемую текущим модулем. Затем используйте команду go mod edit, чтобы заменить требуемый модуль на форк:

<code>$ go list -m example.com/theirmodule
example.com/theirmodule v1.2.3
$ go mod edit -replace=example.com/theirmodule@v1.2.3=example.com/myfork/theirmodule@v1.2.3-fixed
</code>

Примечание: При использовании директивы replace инструменты Go не проверяют подлинность внешних модулей, как описано в разделе Добавление зависимости.

Более подробно о номерах версий см. в разделе Нумерация версий модулей.

Получение конкретного коммита с использованием идентификатора репозитория

Вы можете использовать команду go get для добавления неопубликованного кода модуля из конкретного коммита в его репозитории.

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

Следующие примеры демонстрируют несколько случаев. Они основаны на модуле, исходный код которого находится в git-репозитории.

  • Чтобы получить модуль в конкретном коммите, добавьте форму @commithash:

    <code>$ go get example.com/theirmodule@4cf76c2
    </code>
  • Чтобы получить модуль в конкретной ветке, добавьте форму @branchname:

    <code>$ go get example.com/theirmodule@bugfixes
    </code>

Удаление зависимости

Когда ваш код больше не использует какие-либо пакеты в модуле, вы можете прекратить отслеживание этого модуля как зависимости.

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

<code>$ go mod tidy
</code>

Чтобы удалить конкретную зависимость, используйте команду go get , указывая путь модуля и добавляя @none, как в следующем примере:

<code>$ go get example.com/theirmodule@none
</code>

Команда go get также понизит или удалит другие зависимости, которые зависят от удалённого модуля.

Зависимости инструментов

Зависимости инструментов позволяют управлять инструментами разработки, написанными на Go и используемыми при работе с вашим модулем. Например, вы можете использовать stringer с go generate, или конкретный линтер или форматтер в рамках подготовки изменений к отправке.

В Go 1.24 и выше вы можете добавить зависимость инструмента с помощью:

<code>$ go get -tool golang.org/x/tools/cmd/stringer
</code>

Это добавит директиву tool в ваш файл go.mod и обеспечит наличие необходимых директив require. После добавления этой директивы вы можете запустить инструмент, передав последний непростой версионный компонент пути импорта инструмента в go tool:

<code>$ go tool stringer
</code>

В случае, если несколько инструментов разделяют последнюю часть пути или эта часть совпадает с одним из инструментов, поставляемых вместе с Go, необходимо передавать полный путь пакета:

<code>$ go tool golang.org/x/tools/cmd/stringer
</code>

Чтобы получить список всех доступных инструментов, выполните go tool без аргументов:

<code>$ go tool
</code>

Вы можете вручную добавить директиву tool в ваш go.mod, но вы должны убедиться, что существует директива require для модуля, определяющего инструмент. Простой способ добавления недостающих директив require — выполнить:

<code>$ go mod tidy
</code>

Требования, необходимые для удовлетворения зависимостей инструментов, ведут себя так же, как и любые другие требования в вашем модульном графе. Они участвуют в минимальном выборе версий и уважают директивы require, replace и exclude. Из-за обрезки модулей, когда вы зависите от модуля, который сам имеет зависимость инструмента, требования, существующие только для удовлетворения этой зависимости инструмента, обычно не становятся требованиями вашего модуля.

Мета-паттерн tool предоставляет способ выполнять операции над всеми инструментами одновременно. Например, вы можете обновить все инструменты с помощью go get -u tool, или установить их все в $GOBIN с помощью go install tool.

В версиях Go до 1.24 вы можете достичь чего-то подобного директиве tool, добавив пустой импорт в go-файл внутри модуля, который исключён из сборки с использованием ограничений сборки Если вы сделаете это, вы сможете использовать команду go run с полным путём пакета для запуска утилиты.

Указание сервера прокси модулей

Когда вы используете инструменты Go для работы с модулями, по умолчанию они скачивают модули с proxy.golang.org (публичная зеркальная копия модулей, управляемая Google) или напрямую с репозитория модуля. Вы можете указать, что инструменты Go должны использовать другой сервер прокси для загрузки и аутентификации модулей.

Вы можете сделать это, если вы (или ваша команда) настроили или выбрали другой сервер прокси модулей, который вы хотите использовать. Например, некоторые настраивают сервер прокси модулей, чтобы иметь больше контроля над тем, как используются зависимости.

Чтобы указать другой сервер прокси модулей для использования инструментами Go, установите переменную окружения GOPROXY в URL-адрес одного или нескольких серверов. Инструменты Go будут пробовать каждый URL в порядке, в котором вы их указали. По умолчанию GOPROXY указывает сначала публичный сервер прокси, управляемый Google, а затем прямую загрузку с репозитория модуля (как указано в его пути модуля):

<code>GOPROXY="https://proxy.golang.org,direct"
</code>

Более подробно о переменной окружения GOPROXY, включая значения для поддержки других поведений, см. в справочнике по команде go.

Вы можете установить переменную в URL-адреса других серверов прокси модулей, разделяя URL-адреса либо запятой, либо вертикальной чертой.

  • Когда вы используете запятую, инструменты Go будут пробовать следующий URL в списке только в том случае, если текущий URL возвращает HTTP-ошибку 404 или 410.

    <code>GOPROXY="https://proxy.example.com,https://proxy2.example.com"
    </code>
  • Когда вы используете вертикальную черту, инструменты Go будут пробовать следующий URL в списке независимо от HTTP-кода ошибки.

    <code>GOPROXY="https://proxy.example.com|https://proxy2.example.com"
    </code>

Модули Go часто разрабатываются и распространяются на серверах контроля версий и прокси модулей, которые не доступны в публичном интернете. Вы можете установить переменную окружения GOPRIVATE, чтобы настроить команду go на загрузку и сборку модулей из приватных источников. Таким образом, команда go сможет загружать и собирать модули из приватных источников.

Переменные окружения GOPRIVATE или GONOPROXY могут быть установлены в списки шаблонов glob, соответствующих префиксам модулей, которые являются приватными и не должны запрашиваться с любого прокси. Например:

<code>GOPRIVATE=*.corp.example.com,*.research.example.com
</code>
GoRu.dev Golang на русском

На сайте представлена адаптированная под русский язык документация языка программирования Golang