Модуль
1Пакеты: основы2Go модули← вы здесь3Тестирование4Инструменты Go
Урок 2~12 минут

Go модули

Жизнь до и после Go Modules

До Go 1.11 существовал GOPATH — одна папка куда нужно было складывать весь Go-код. Это было неудобно: нельзя иметь разные версии одной зависимости в разных проектах, путь проекта был привязан к файловой системе.

Go Modules (Go 1.11, обязательны с Go 1.16) решили эту проблему: проект может лежать где угодно, каждый проект имеет свой список зависимостей с точными версиями.


go.mod: манифест проекта

bash
go mod init github.com/mycompany/myapp

Создаёт go.mod:

go
module github.com/mycompany/myapp
 
go 1.22
 
require (
    github.com/gin-gonic/gin v1.9.1
    github.com/lib/pq v1.10.9
)

Три части:

  • module — имя модуля (путь для импорта внутренних пакетов)
  • go — минимальная версия Go
  • require — прямые зависимости с точными версиями

Имя модуля используется в импортах:

go
// Если module = github.com/mycompany/myapp
// то внутренний пакет myapp/user/store импортируется как:
import "github.com/mycompany/myapp/user/store"

go.sum: замок на безопасность

go.sum создаётся автоматически и содержит хэши всех зависимостей:

github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=

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

Важно: go.sum нужно коммитить в git. Без него другой разработчик может получить другую версию зависимости.


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

bash
# Добавить зависимость (последняя версия)
go get github.com/gin-gonic/gin
 
# Добавить конкретную версию
go get github.com/gin-gonic/gin@v1.9.1
 
# Обновить до последней minor/patch версии
go get -u github.com/gin-gonic/gin
 
# Удалить зависимость из кода и go.mod
go mod tidy
 
# Скачать все зависимости локально (для offline работы)
go mod download
 
# Проверить зависимости
go mod verify

go mod tidy — самая важная команда. Запускай её после:

  • Добавления/удаления импортов
  • Обновления зависимостей
  • Перед коммитом

Семантическое версионирование

Go modules строго следуют SemVer: vMAJOR.MINOR.PATCH

  • PATCH (v1.0.1): баг-фиксы, обратная совместимость сохранена
  • MINOR (v1.1.0): новые фичи, обратная совместимость сохранена
  • MAJOR (v2.0.0): ломающие изменения API

Главное правило Go modules: мажорная версия ≥ 2 входит в путь импорта:

go
// v1 — обычный путь
import "github.com/user/pkg"
 
// v2 — версия в пути!
import "github.com/user/pkg/v2"
 
// v3
import "github.com/user/pkg/v3"

Это позволяет использовать v1 и v2 одной библиотеки в одном проекте — они разные пакеты с точки зрения Go.


Псевдо-версии и pre-release

Иногда нужна версия из конкретного коммита — до тега:

bash
# Получить последний коммит из ветки
go get github.com/user/pkg@main
 
# Конкретный коммит
go get github.com/user/pkg@abc1234

Go создаст псевдо-версию в go.mod:

github.com/user/pkg v0.0.0-20240115123456-abc1234abcde

Формат: v0.0.0-{дата}-{хэш коммита}.


replace: локальная разработка

Когда работаешь одновременно над несколькими связанными модулями:

go
// go.mod
module github.com/mycompany/service
 
require (
    github.com/mycompany/shared v1.2.0
)
 
// Переключаем на локальную копию для разработки
replace github.com/mycompany/shared => ../shared

Теперь service использует локальную папку ../shared вместо скачанной версии. Не забудь убрать replace перед коммитом — иначе сборка сломается у других.


Vendor: зависимости в репозитории

bash
go mod vendor

Копирует все зависимости в папку vendor/. Плюсы:

  • Сборка работает без интернета
  • Полный контроль над кодом зависимостей
  • Часть команд требует этого (некоторые корпоративные среды)
bash
# Сборка с vendor
go build -mod=vendor ./...
 
# Проверить что vendor актуален
go mod verify

Минус: vendor/ может быть огромным (сотни МБ). Многие проекты предпочитают не коммитить его и полагаться на кэш модулей ($GOPATH/pkg/mod).


Рабочее пространство (workspace)

Go 1.18 добавил go work для работы с несколькими модулями одновременно:

bash
go work init ./service ./shared ./proto

Создаёт go.work:

go 1.22

use (
    ./service
    ./shared
    ./proto
)

Теперь все три модуля видят изменения друг друга без replace. go.work не коммитить в git — это локальный инструмент разработчика.

go.mod — это список зависимостей проекта. go.sum — контрольные суммы для безопасности. Никогда не редактируй их вручную — используй go get, go mod tidy. GOPATH больше не нужен.
Имя модуля
github.com/user/app
go.mod
module github.com/user/app go 1.21 require (github.com/gorilla/mux v1.8.0github.com/sirupsen/logrus v1.9.3 // indirect — unused)
Внутренние импорты используют имя модуля
// main.go import ("fmt""github.com/user/app/store" // внутренний пакет store"github.com/user/app/handlers" // внутренний пакет handlers)
Имя модуля — это корень всех внутренних путей импорта. При переименовании нужно обновить все импорты.
🎯
Миссия 1 из 4
Какая команда инициализирует новый Go модуль?