среда, 24 марта 2021 г.

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

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

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

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

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

Ниже перечислены наиболее распространенные шаги управления зависимостями.

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

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

В Go вы управляете зависимостями как модулями, которые содержат импортируемые вами пакеты. Этот процесс поддерживается:

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

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

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

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

import "rsc.io/quote"

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

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

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

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

$ go mod init example.com/mymodule

Аргументом команды go mod init является путь к модулю вашего модуля. Если возможно, путь к модулю должен быть местоположением репозитория вашего исходного кода. Если сначала вы не знаете возможное местоположение репозитория модуля, рассмотрите возможность временного использования безопасной замены, такой как имя вашего домена или example.com, а также путь, следующий из имени модуля или исходного каталога.

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

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

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

Добавление зависимости

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

Команда делает следующее:

  • При необходимости она добавляет в файл go.mod директивы require для модулей, необходимых для сборки пакетов, названных в командной строке. Директива require отслеживает минимальную версию модуля, от которой зависит ваш модуль.
  • При необходимости она загружает исходный код модуля, чтобы вы могли компилировать пакеты, зависящие от них. Она может загружать модули с прокси-сервера модуля, такого как proxy.golang.org, или непосредственно из репозиториев системы контроля версий. Источник кешируется локально.
    Вы можете указать место, откуда инструменты Go загружают модули.

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

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

    $ go get .
    

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

    $ go get example.com/theirmodule
    

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

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

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

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

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

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

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

    $ go get example.com/theirmodule@v1.3.4
    

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

    $ go get example.com/theirmodule@latest
    

В следующем примере директивы require для файла go.mod показано, как требовать конкретный номер версии:

require example.com/theirmodule v1.3.4

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

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

Вот пара примеров.

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

    $ go list -m -u all
    

  • Показать последнюю версию, доступную для конкретного модуля:

    $ go list -m -u example.com/theirmodule
    

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

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

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

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

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

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

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

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

$ go mod tidy

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

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

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

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

Требование кода модуля в локальном каталоге

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

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

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

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

module example.com/mymodule

go 1.16

require example.com/theirmodule v0.0.0-unpublished

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

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

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

Примечание. Когда вы используете директиву replace, инструменты Go не аутентифицируют внешние модули.

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

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

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

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

module example.com/mymodule

go 1.16

require example.com/theirmodule v1.2.3

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

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

$ 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

Примечание. Когда вы используете директиву replace, инструменты Go не аутентифицируют внешние модули.

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

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

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

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

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

    $ go get example.com/theirmodule@4cf76c2
    

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

    $ go get example.com/theirmodule@bugfixes
    

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

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

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

$ go mod tidy

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

$ go get example.com/theirmodule@none

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

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

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

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

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

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

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

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

GOPROXY="https://proxy.example.com,https://proxy2.example.com"

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

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


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


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

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