Почему я перестал использовать init()
init() удобен: положил туда подключение к базе или чтение конфига, и оно «просто работает». Проблемы начинаются позже.
Неявный порядок
Порядок вызова init() зависит от графа импортов и порядка файлов в пакете. Добавили импорт — и инициализация пошла в другом порядке.
Тесты
init() выполняется при любом импорте пакета, в том числе в тестах. Если он лезет в сеть или читает переменные окружения, юнит-тест внезапно требует живую базу.
Что вместо
func main() {
cfg := mustLoadConfig()
db := mustOpenDB(cfg.DSN)
defer db.Close()
run(cfg, db)
}
Явная инициализация в main длиннее на пару строк, зато зависимости видны, а тесты собирают ровно то, что им нужно.