Почему я перестал использовать init()

3 июня 2026

init() удобен: положил туда подключение к базе или чтение конфига, и оно «просто работает». Проблемы начинаются позже.

Неявный порядок

Порядок вызова init() зависит от графа импортов и порядка файлов в пакете. Добавили импорт — и инициализация пошла в другом порядке.

Тесты

init() выполняется при любом импорте пакета, в том числе в тестах. Если он лезет в сеть или читает переменные окружения, юнит-тест внезапно требует живую базу.

Что вместо

func main() {
    cfg := mustLoadConfig()
    db := mustOpenDB(cfg.DSN)
    defer db.Close()
    run(cfg, db)
}

Явная инициализация в main длиннее на пару строк, зато зависимости видны, а тесты собирают ровно то, что им нужно.