В Go глобальные переменные инициализируются в порядке объявления файлов и последовательности их init-функций. От этого зависит корректность обращения к глобальному состоянию: если переменная в одном пакете зависит от значения переменной другого пакета, но этот пакет еще не был инициализирован — возникнет ошибка или неочевидное поведение.
Прямого объявления "стартового порядка" между init-функциями разных пакетов нельзя задать. Компилятор определяет этот порядок исходя из графа импорта.
main.main().Пример безопасной отложенной инициализации (lazy init):
var cfg *Config var once sync.Once func GetConfig() *Config { once.Do(func() { cfg = LoadConfigFromDisk() }) return cfg }
Вопрос: Могут ли init-функции разных пакетов выполняться одновременно (параллельно) при запуске программы на Go?
Правильный ответ: Нет, init-функции и глобальные переменные выполняются строго последовательно в порядке определённого компилятором при анализе зависимостей между пакетами. Параллельного запуска init-функций не происходит.
История
В крупном проекте несколько модулей грузили глобальные конфиги с диска через init(). Один модуль зависел от другого, но в силу переустройства графа go.mod порядок инициализации поменялся — и внезапно значения конфига оказались пустыми! Ошибка проявлялась случайным образом, зависящим от порядка сборки, и нашлась только после разбора зависимостей и перевода инициализации в явную функцию.
История
В REST-сервисе для кэширования справочников использовался глобальный map без mutex. Инициализация начиналась из нескольких goroutine, стартовавших в init. Как результат — data race, периодические паники, невалидные данные внутри map. После замены на sync.Once и явного вызова инициализации проблема ушла.
История
Глобальный логгер создавался в init-функции одного из вспомогательных пакетов, однако другой пакет обращался к этому логгеру тоже при старте, до его инициализации. В итоге часть логов о старте терялась, пока логгер ещё не существовал. Решение — инъекция зависимостей и явная инициализация логгера до запуска всех сервисов.