Go поддерживает функцию init для выполнения кода инициализации до начала main(). При запуске программы Go компилятор автоматически вызывает все функции init, объявленные в каждом пакете, после инициализации переменных пакета.
История вопроса: необходимость однократной подготовки состояния пакета до его использования.
Проблема: порядок инициализации init часто становится причиной неявных ошибок: сложно контролировать, когда именно сработает конкретная init-функция, особенно при множестве зависимостей между пакетами.
Решение:
Пример кода:
package example import "fmt" var Cfg string = "default" func init() { fmt.Println("example init") Cfg = "configured" }
Ключевые особенности:
Можно ли определить больше одной init-функции в одном файле?
Да, допускается несколько init-функций — они вызовутся в порядке их объявления.
Что произойдет, если пакет импортируется только побочно (через _ "package")?
Выполнятся только init функции и инициализация переменных этого пакета.
Init-функции могут возвращать значение или ошибку?
Нет. Сигнатура init неизменна: func init(), без параметров и возвращаемых значений.
Крупный проект полагался на сложные init-функции, инициализирующие глобальные состояния с зависимостями между пакетами. Причиняло плавающие ошибки запуска.
Плюсы:
Минусы:
Init используется только для базовых или test-specific задач, остальное вынесено в явные функции, вызываемые из main(). Очевиден порядок запуска, простота тестирования.
Плюсы:
Минусы: