К содержимому
Содержание

Go Modules: go mod tidy и управление зависимостями

Добавили или удалили импорт пакета и хотите привести зависимости проекта в порядок? go mod tidy согласует go.mod и go.sum с кодом: добавляет недостающие требования к модулям и контрольные суммы, удаляет ненужные. Разбор команды с примером объясняет, какие изменения проверить после запуска.

Почти любой реальный проект использует чужой код: HTTP-роутер, драйвер PostgreSQL, библиотеку для UUID, YAML-парсер, Telegram SDK. Такой внешний код называется зависимостью.

Управление зависимостями отвечает на практические вопросы:

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

В Go для этого используется система Go Modules.

Модуль

Модуль - это корень Go-проекта с файлом go.mod. Обычно один репозиторий содержит один модуль.

Создать модуль:

go mod init github.com/username/weather-cli

После этого появится go.mod:

module github.com/username/weather-cli go 1.22

module задает module path. Если проект будет опубликован на GitHub, обычно используют путь репозитория. Для учебного локального проекта можно использовать условный путь, но лучше сразу привыкать к реальному формату.

Import path

Пакеты внутри модуля импортируются относительно module path:

github.com/username/weather-cli/internal/config

Если в go.mod написано:

module github.com/username/weather-cli

а пакет лежит в:

internal/config

то import будет:

import "github.com/username/weather-cli/internal/config"

Если module path выбран случайно, импорты тоже станут случайными. Поэтому имя модуля лучше выбирать внимательно.

О том, как разделить код на пакеты и когда использовать internal, читайте в статье «Структура Go проектов».

go.mod

go.mod хранит:

  • имя модуля;
  • версию Go;
  • прямые зависимости;
  • иногда indirect dependencies;
  • replace directives, если они нужны локально.

Пример:

module github.com/username/books-api go 1.22 require ( github.com/go-chi/chi/v5 v5.0.12 github.com/google/uuid v1.6.0 )

Этот файл нужно коммитить. Без него другой человек не поймет, какие зависимости нужны проекту.

go.sum

go.sum хранит checksums зависимостей. Он помогает Go проверить, что скачанный код совпадает с ожидаемым.

go.sum тоже нужно коммитить. Это не временный файл и не lock-файл в привычном смысле, но он важен для воспроизводимости и безопасности.

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

Чтобы добавить зависимость:

go get github.com/google/uuid

После этого можно импортировать пакет:

import "github.com/google/uuid" id := uuid.NewString()

Go обновит go.mod и go.sum.

Часто зависимость добавляется автоматически при:

go mod tidy

если импорт уже есть в коде.

Версии

Go Modules используют semantic versioning:

v1.2.3
  • 1 - major;
  • 2 - minor;
  • 3 - patch.

Patch обычно содержит исправления. Minor добавляет функциональность без ломания совместимости. Major может ломать API.

Для major version v2+ в Go меняется import path:

import "github.com/go-chi/chi/v5"

Это не случайность. Go делает major version частью пути, чтобы разные major versions могли сосуществовать.

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

Обновить до последней совместимой версии:

go get github.com/google/uuid@latest

Указать конкретную версию:

go get github.com/go-chi/chi/v5@v5.0.12

После обновления запускайте тесты:

go test ./...

Даже minor update может изменить поведение в деталях.

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

Чтобы удалить зависимость:

  1. Удалите import из кода.
  2. Удалите использование пакета.
  3. Выполните:
go mod tidy

tidy удалит требование к модулю из go.mod, если его пакеты больше не нужны, и уберёт ненужные контрольные суммы из go.sum. Если пакет нужен тестам или другим зависимостям, модуль может остаться.

go mod tidy

Запускайте go mod tidy из каталога проекта, где находится go.mod. Команда проверяет зависимости пакетов и:

  • добавляет в go.mod недостающие требования к модулям;
  • удаляет требования к модулям, пакеты которых больше не нужны;
  • добавляет недостающие и удаляет ненужные контрольные суммы в go.sum.

Например, вы убрали из проекта использование uuid.NewString() и импорт github.com/google/uuid. В Git-репозитории выполните:

go mod tidy git diff -- go.mod go.sum go test ./...

Если пакеты этого модуля больше нигде не нужны, в изменениях go.mod исчезнет требование к github.com/google/uuid. В go.sum будут удалены его ненужные контрольные суммы. Если файлы уже соответствуют коду, изменений может не быть.

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

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

Подробные правила описаны в официальном справочнике Go Modules.

Indirect dependencies

В go.mod можно увидеть:

require github.com/some/package v1.2.3 // indirect

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

replace

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

replace github.com/example/lib => ../lib

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

Чеклист

  1. В корне проекта есть go.mod.
  2. Module path выбран осознанно.
  3. go.mod и go.sum закоммичены.
  4. Зависимости добавляются через go get или go mod tidy.
  5. Неиспользуемые зависимости удаляются через go mod tidy.
  6. После обновления зависимостей запускаются тесты.
  7. replace не содержит локальных путей перед публикацией.

Следующий шаг после статьи

Закрепите тему во вводном проекте без регистрации, а затем переходите к курсам.

Продолжить изучение

Следующая статья по теме или материалы для более подробного разбора.

Похожие статьи