Wanneer een Go-applicatie wordt opgestart, worden alle non-test-pakketten strikt in een bepaalde volgorde geïnitialiseerd: eerst worden alle geïmporteerde afhankelijkheden (in keten) geïnitialiseerd, daarna het pakket zelf. Voor initialisatie worden gebruikt:
Init-functies worden aangeroepen na de initialisatie van de pakketvariabelen. Als een pakket wordt geïmporteerd, wordt de init eenmaal uitgevoerd voordat de variabelen/functies van dat pakket worden gebruikt.
Voorbeeld:
var a = getA() func getA() int { fmt.Println("getA aangeroepen") return 42 } func init() { fmt.Println("init aangeroepen") } // Geeft weer: // getA aangeroepen // init aangeroepen
Kenmerken:
Kan ik de init-functie van elk pakket expliciet aanroepen?
Antwoord: Nee, de init-functie wordt nooit direct vanuit de programmacode aangeroepen. Ze wordt alleen door de runtime aangeroepen tijdens het initialisatieproces van het pakket op een vooraf bepaald moment, expliciete aanroep van init() is niet toegestaan — dit zal leiden tot een compilatiefout.
Verhaal
In een project importeerden twee pakketten elkaar om globale variabelen via init() te initialiseren. Dit leidde tot cyclische afhankelijkheden en fouten bij de build — Go kon de juiste volgorde van initialisatie niet bepalen.
Verhaal
De oorzaak van een complexe bug was dat de init-functies globale pakketvariabelen gebruikten die nog niet waren geïnitialiseerd. Resultaat: ambigu gedrag bij uitvoering met onvoorspelbare toestanden.
Verhaal
In een project werd een pakket voor side effects geïmporteerd zonder expliciet gebruik (via import _ "some/lib"). Na herorganisatie van de code werd de init-functie van het benodigde pakket te vroeg aangeroepen (voor de initialisatie van de afhankelijkheidsvariabelen in een ander pakket), wat leidde tot een hard-to-debug bug.