Перейти к основному содержимому

Модули, workspace, embed и slog

Разработчику Архитектору

См. также: Функции и методы — модули · Первая программа · Рекомендации.

go.mod и кэш модулей

Файл go.mod задаёт путь модуля, версию Go и зависимости. Команда go mod download кладёт модули в кэш (обычно $GOPATH/pkg/mod), общий для всех проектов на машине.

  • go mod tidy — синхронизировать зависимости с импортами;
  • go mod verify — проверить хэши в go.sum;
  • go get example.com/pkg@v1.2.3 — добавить или обновить зависимость.

go.sum фиксирует криптографические хэши — защита supply chain при повторной сборке.


Каталог vendor

go mod vendor

Создаёт копию всех зависимостей в ./vendor. Сборка с флагом -mod=vendor (или переменная GOFLAGS=-mod=vendor) берёт код из vendor, а не из сетевого кэша.

Когда нужен vendorКогда достаточно кэша
CI без доступа в интернетОбычная разработка
Жёсткая воспроизводимость артефактаgo.sum + proxy
Корпоративная политика

vendor не заменяет go.mod: версии по-прежнему объявлены в модуле. replace в go.mod действует и при vendor-сборке.


go work — несколько модулей в одном репозитории

Workspace связывает несколько go.mod без постоянных replace в каждом проекте:

go work init ./services/api ./services/worker ./pkg/common

Файл go.work:

go 1.22

use (
./services/api
./services/worker
./pkg/common
)

Локальные изменения в pkg/common сразу видны зависимым модулям при go build из корня workspace. Для публикации в CI часто собирают конкретный подмодуль; go.work обычно в .gitignore или коммитят для монорепо команды.

Отличие от replace github.com/me/lib => ../lib в одном go.mod: go work масштабируется на N сервисов без дублирования директив.


embed — статика в бинарнике

Пакет embed (Go 1.16+) встраивает файлы при компиляции:

import "embed"

//go:embed static/*
var staticFS embed.FS

//go:embed config/default.yaml
var defaultConfig []byte

Ограничения:

  • путь только относительно пакета, без ..;
  • переменная должна быть на уровне пакета;
  • шаблоны в комментарии //go:embed обязательны.

Раздача в HTTP:

http.Handle("GET /static/", http.FileServer(http.FS(staticFS)))

Удобно для SPA, иконок, встроенных миграций SQL без отдельного тома в контейнере.


log/slog — структурированные логи

С Go 1.21 в стандартной библиотеке — log/slog:

logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelInfo,
}))
logger.Info("request done",
"method", r.Method,
"path", r.URL.Path,
"ms", elapsed.Milliseconds(),
)

Пары ключ–значение лучше, чем fmt.Sprintf в сообщении: системы вроде Loki/ELK индексируют поля.

Уровни: Debug, Info, Warn, Error. Контекст:

logger = logger.With("request_id", id)
logger.Error("db", "err", err)

Свой slog.Handler подключает Zap, Logrus и корпоративные форматы без смены вызовов в коде (интерфейсы).


Связка в проекте

Типичный сервис в монорепо:

  1. go.work для локальной разработки библиотек;
  2. go.mod в каждом сервисе для релиза;
  3. go mod vendor в CI при офлайн-сборке;
  4. //go:embed для OpenAPI/UI или дефолтного конфига;
  5. slog + JSON в stdout для Kubernetes.

Подробнее о модулях в коде — функции и методы, первый проект — первая программа.


См. также

Другие статьи этого же раздела в боковом меню (как на странице «О разделе»).