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 может изменить поведение в деталях.
Удаление зависимости
Чтобы удалить зависимость:
- Удалите import из кода.
- Удалите использование пакета.
- Выполните:
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 сломает проект у других людей.
Чеклист
- В корне проекта есть
go.mod. - Module path выбран осознанно.
go.modиgo.sumзакоммичены.- Зависимости добавляются через
go getилиgo mod tidy. - Неиспользуемые зависимости удаляются через
go mod tidy. - После обновления зависимостей запускаются тесты.
replaceне содержит локальных путей перед публикацией.