---
name: "x-doc-go"
description: "Применяй при создании нового пакета или изменении существующего package contract: наличие `doc.go`, структура package comment, секция `Конфигурация`, ограничения, doc-комментарии экспортируемых символов и тестируемые примеры `Example...`"
---
# doc.go

Если нужен быстрый smoke-check пакета, используй `scripts/check-doc-go.sh <package-dir>`.

## Шаг 1: Проверь наличие doc.go

Каждый пакет и подпакет **обязан** иметь `doc.go`. Если его нет — создай.

**Исключения** — `doc.go` не требуется:

- `cmd/app/` и другие `cmd/*` пакеты — точки входа приложения, не имеют переиспользуемого контракта.
- `mocks/` - это автогенерация.

## Шаг 2: Прочитай doc.go перед началом работы

`doc.go` — это контракт пакета. Читай его первым при входе в любую директорию пакета.

## Шаг 3: Напиши или обнови package-level комментарий

Комментарий должен содержать четыре секции:

1. **Что реализует** — какой интерфейс и из какого пакета
2. **Точка входа** — какой конструктор использовать
3. **Переменные окружения** — список с дефолтами
4. **Ограничения** — потокобезопасность, обязательный `Close()`, порядок вызовов

```go
// Package {name} реализует интерфейс {parent}.{Interface} для {Service}.
//
// Использование:
//
//	instance := {name}.New(cfg)
//	defer instance.Close()
//
// Конфигурация:
//
//	{ENV_VAR_1}  — описание (default: value)
//	{ENV_VAR_2}  — описание (default: value)
//
// Ограничения:
//
//	- Потокобезопасность: да/нет
//	- Требует Close() для освобождения ресурсов
//	- {другие ограничения}
package {name}
```

## Шаг 4: Проверь doc-комментарии экспортируемых символов

Каждый экспортируемый тип, функция и метод **обязан** иметь doc-комментарий — полное предложение на русском, заканчивается точкой (см. AGENTS.md, Global Conventions).

Формат: `// ИмяСимвола описание действия.`

```go
// CreatePoint создаёт точку с заданными координатами.
func (s *Service) CreatePoint(ctx context.Context, x, y float64) (*domain.Point, error) {
```

**Исключения** — doc-комментарий не требуется:
- Методы, сгенерированные кодогенератором (gqlgen, protoc и т.д.)
- Неэкспортируемые символы (начинаются с маленькой буквы)

**Проверка** — найди экспортируемые символы без doc-комментария:
```
rg -n "^(func|type) " -g '*.go' -g '!**/*_test.go' -g '!**/mocks/**' .
```
Для каждого символа с заглавной буквы убедись, что строкой выше есть `// ИмяСимвола ...`.

## Шаг 5: Синхронизируй с кодом

`doc.go` должен отражать актуальное состояние пакета. При каждом PR — проверь что переменные окружения, конструктор и ограничения актуальны.

## Шаг 6: Добавь тестируемые примеры, если они заменяют документационный сниппет

Если публичный контракт пакета, функции или типа проще понять через короткий рабочий пример, оформи его как Go example test:

- `Example()` — пример пакета
- `ExampleFunc()` — пример функции `Func`
- `ExampleType()` — пример типа `Type`
- `ExampleType_Method()` — пример метода `Type.Method`

Пример должен жить в `*_test.go` рядом с пакетом и печатать наблюдаемый результат. Ожидаемый вывод фиксируй в комментарии `Output:` — тогда `go test` проверит, что пример не устарел.

```go
func ExampleNormalizeName() {
	fmt.Println(NormalizeName("  Alice  "))
	// Output: Alice
}
```

Используй `Example...`, когда иначе пришлось бы вставлять в `doc.go` или doc-комментарий проверяемый фрагмент кода с ожидаемым результатом. Не добавляй примеры ради формальности: для очевидных конструкторов и boilerplate достаточно обычного раздела `Использование` в `doc.go`.

## Пример

```go
// Package redis реализует интерфейс kv.Store для Redis.
//
// Использование:
//
//	store := redis.New(cfg)
//
// Конфигурация:
//
//	REDIS_ADDR     — адрес сервера (default: localhost:6379)
//	REDIS_PASSWORD — пароль
//	REDIS_DB       — номер базы данных (default: 0)
package redis
```

## Эталонные варианты doc.go для разных типов пакетов

### Корневой пакет конфигурации

- пакет сразу объясняет, что конфиг грузится из окружения
- перечисляет верхнеуровневые переменные
- не расписывает до бесконечности вложенные платформенные конфиги, а даёт ориентир, где смотреть дальше

Это хороший паттерн для корневого `Config` приложения.

### Длинный прикладной список переменных окружения

- допустим, когда пакет реально владеет большим количеством прикладных переменных
- в таком случае длинная секция `Конфигурация` — часть контракта, а не шум

Используй этот стиль, когда у пакета много собственных env и они нужны как явный публичный договор.

### Legacy-совместимость

- можно явно описывать устаревшие алиасы
- нужно указывать приоритет новых переменных
- миграция env — это часть контракта пакета, если она реально поддерживается

### Что должно читаться сразу

Хороший `doc.go` позволяет за минуту понять:

- что делает пакет
- какая у него точка входа
- какие env нужны
- какие ограничения или правила жизненного цикла нельзя нарушать

## Не делай

- не заменяй `doc.go` на `README.md` внутри пакета
- не оставляй `doc.go` в состоянии, которое уже не совпадает с кодом
- не пропускай секцию `Ограничения`, если пакет требует `Close()`, lifecycle или special order of calls
- не пиши doc-комментарии экспортируемых символов на английском

## Полезные ресурсы

- `scripts/check-doc-go.sh` — проверка наличия и базовой структуры `doc.go`
