Перейти к основному содержимому
Модуль 9 · Урок 4 из 544/50 в курсе~12 min
Уроки модуля (4/5)

Модули Go

Модуль Go — это модуль с поддержкой версий, состоящий из одного или нескольких пакетов. Это основа современной системы зависимостей (Go 1.11+): больше никаких GOPATH, никаких обязательных vendor, явные и воспроизводимые зависимости.

go.mod: манифест модуля

Code
module example.com/myapp

go 1.22

require (
    github.com/google/uuid v1.6.0
    golang.org/x/time     v0.5.0
)

Три основные директивы:

  • module <path> — путь импорта модуля. Все внутренние пакеты импортируются как example.com/myapp/sub/pkg. Это не обязательно должен быть настоящий URL-адрес, но для публикации через go get он должен быть разрешен.
  • go <version> — минимальная требуемая версия Go (также используется для управления тем, какие языковые функции разрешены, например, range-over-func в 1.23).
  • require — прямые зависимости с их точной версией.

Другие директивы: replace (заменяет dep ответвлением или локальным путем), exclude, retract.

go.sum: файл криптографической блокировки.

Наряду с go.mod, go.sum содержит криптографический хеш КАЖДОЙ загруженной версии (включая транзитивные зависимости). Это гарантирует воспроизводимость: если кто-то подделает опубликованную версию, сборка завершится неудачей.

Всегда фиксируйте его. Он обновляется автоматически командами go.

Основные команды

Bash
go mod init example.com/myapp        # create go.mod
go get github.com/google/uuid        # add the dep at its latest version
go get github.com/google/uuid@v1.5.0 # specific version
go get -u ./...                      # upgrade every dep
go mod tidy                          # remove unused deps, add missing ones
go mod download                      # download everything into the cache
go mod why github.com/x/y            # explain why a dep is included
go mod graph                         # full dependency graph

go mod tidy — это тот, который вы запускаете после каждого изменения импорта: он гарантирует, что go.mod точно отражает фактически используемые пакеты.

Семантическое управление версиями импорта (SIV)

Версии соответствуют SemVer: v1.2.3 = MAJOR.MINOR.PATCH. Самое интересное — major v2+:

  • Основные v0 и v1 → обычный путь: github.com/foo/bar.
  • Основная версия v2 или более поздняя → путь включает основную версию: github.com/foo/bar/v2.
Go
import "github.com/foo/bar/v2"

Это позволяет одновременно импортировать v1 и v2 одной и той же библиотеки (полезно при прогрессивной миграции).

Импорт путей и внутренних пакетов

Если ваш модуль example.com/myapp, подпапка utils/ импортируется как:

Go
import "example.com/myapp/utils"

Путь зависит только от имени, объявленного в go.mod, а не от местоположения на диске: тот же код в другой папке продолжает работать.

Режим рабочей области (Go 1.18+)

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

Bash
go work init ./lib ./app

При этом создается go.work: go build будет использовать локальную версию ./lib вместо загрузки опубликованной. Не делайте коммит go.work (это среда разработки).

Упражнения

Упражнение#go.m9.l4.e1
Попыток: 0Загрузка…

Модуль находится по адресу example.com/myapp и содержит подпапку utils. Импортируйте подпакет в основной, используя полный путь.

Загрузка редактора…
Показать подсказку

Путь импорта — это имя модуля (из go.mod) плюс относительный путь к папке.

Решение доступно после 3 попыток

Упражнение#go.m9.l4.e2
Попыток: 0Загрузка…

Превратите отдельные импортированные файлы в группу импорта с помощью синтаксиса импорта (...), импортируя как fmt, так и os.

Загрузка редактора…

Решение доступно после 3 попыток

Quiz#go.m9.l4.e3
Готово

Какая команда удаляет зависимости, которые больше не импортируются из go.mod, и добавляет недостающие?

Go
$ go mod ???
Варианты ответа