Почему документация в Go — это суперсила, а не скучная обязанность
Представьте: вы открываете чужой Go-проект, а там — ни одного комментария. Функции называются f1, f2, а структуры — Data и MoreData. Знакомо? Если да, то вы знаете, как быстро энтузиазм сменяется желанием закрыть репозиторий.
Go — язык, который обожает простоту и ясность. Но даже самый чистый код не всегда говорит сам за себя. Хорошая документация в Go — это не просто «добрый жест» для коллег. Это профессиональный инструмент, который:
- Ускоряет онбординг новых разработчиков;
- Помогает избегать багов (вы же помните, что комментарии могут спасти от неверного использования API?);
- Автоматически генерирует красивые страницы на pkg.go.dev;
- Повышает качество кода (попробуйте написать комментарий к плохой функции — сами захотите её переписать).
В этой статье мы разберём лучшие практики документирования Go-проектов. От базовых правил godoc до реальных примеров, которые вы сможете применить уже сегодня. Поехали!
Философия документации в Go: меньше слов — больше смысла
Go — не Java и не Python. Здесь никто не пишет многостраничные Javadoc или docstrings на 20 строк. Философия Go проста: документируйте поведение, а не реализацию.
В официальном руководстве Effective Go чётко сказано: комментарии должны описывать что делает код, а не как. Если ваш код настолько сложный, что без объяснения алгоритма не обойтись — возможно, его стоит упростить.
Основные принципы:
- Комментарий — это предложение. Начинайте с имени функции или типа.
// Calculate returns the result of the calculation.— отлично.// This function calculates...— теряем фокус. - Пишите на английском. Go — интернациональный язык, и документация на английском — стандарт де-факто. Но если ваш проект строго для русскоязычной команды, можно и на русском. Главное — единообразие.
- Не объясняйте очевидное.
// SetName sets the name— бесполезно. Лучше:// SetName updates the user's display name. Must be called before Save.
Godoc: ваш лучший друг и автоматический документовод
Go поставляется со встроенным инструментом godoc. Он парсит комментарии прямо из кода и создаёт HTML-документацию. Это значит, что ваша документация живёт рядом с кодом — и обновляется одновременно.
Как это работает? Очень просто. Напишите комментарий непосредственно перед экспортируемой сущностью (функцией, типом, структурой, константой) — и godoc подхватит его.
Пример базового пакета:
// Package calculator provides basic arithmetic operations.
package calculator
// Add returns the sum of two integers.
func Add(a, b int) int {
return a + b
}
// Subtract returns the difference of two integers.
func Subtract(a, b int) int {
return a - b
}
Теперь запустите godoc -http :8080 и откройте браузер. Вы увидите красивую страницу с описанием пакета и каждой функции. Магия!
Правила хорошего тона для godoc
- Всегда комментируйте пакет. Комментарий пакета — это первое, что видит пользователь. Он должен описывать назначение пакета, а в идеале — содержать пример использования.
- Не забывайте про типы и структуры. Если структура имеет поля, которые не очевидны из названия, документируйте и их.
- Используйте пустую строку.
godocвоспринимает первый абзац как краткое описание, а всё остальное — как подробности. Разделяйте их пустой строкой.
// User represents a registered user in the system.
// It contains all necessary profile information.
//
// Fields:
// - ID: unique identifier
// - Email: must be a valid email address
type User struct {
ID int
Email string
}
Пишем примеры, которые работают: пакет example_test
Лучшая документация — это рабочий код. В Go есть гениальная фича: файлы с суффиксом _test.go могут содержать функции-примеры. Они не только документируют API, но и проверяются компилятором!
Как это выглядит:
// В файле example_test.go
package calculator
import "fmt"
func ExampleAdd() {
sum := Add(2, 3)
fmt.Println(sum)
// Output: 5
}
Когда вы запустите go test, этот пример выполнится. Если вывод не совпадёт с // Output: 5, тест упадёт. А на pkg.go.dev этот код будет отображаться как живой пример, который можно скопировать и запустить.
Советы по примерам:
- Название функции должно быть
Example+ имя функции/типа. Например,ExampleUser_Saveдля методаSaveструктурыUser. - Пишите короткие, самодостаточные примеры. Один пример — один сценарий использования.
- Используйте комментарий
// Output:для демонстрации результата. Это обязательное условие для автоматического тестирования.
Документируем сложные структуры и интерфейсы
Структуры и интерфейсы — это сердце любого Go-приложения. Их документация должна отвечать на вопросы: «Зачем это нужно?» и «Как этим пользоваться?».
Рассмотрим пример интерфейса хранилища данных:
// Storage defines the interface for data persistence.
// Implementations must be safe for concurrent use.
type Storage interface {
// Save persists the given data. Returns an error if the data already exists.
Save(data []byte) error
// Load retrieves data by key. Returns ErrNotFound if missing.
Load(key string) ([]byte, error)
}
Обратите внимание: мы не просто написали «Save saves data». Мы указали:
- Условия вызова (
safe for concurrent use); - Ожидаемое поведение при ошибке (
ErrNotFound); - Побочные эффекты (
returns error if data already exists).
Такой подход избавляет разработчиков от необходимости читать исходный код каждой реализации.
Документирование констант и ошибок
Константы и переменные ошибок тоже заслуживают внимания. Особенно если их много.
// Predefined errors returned by the storage package.
var (
// ErrNotFound is returned when a key is not found in the storage.
ErrNotFound = errors.New("key not found")
// ErrDuplicate is returned when attempting to save an existing key