ProgrammatieGo ontwikkelaar

Leg uit hoe defer werkt in Go en wanneer de volgorde van aanroepen verrassend kan zijn. Welke valkuilen komen in de praktijk voor?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

Het trefwoord defer in Go stelt het uitvoeren van opgegeven functies uit tot het verlaten van de omringende functie — functies worden op de stack opgeslagen en in omgekeerde volgorde uitgevoerd (LIFO). Dit wordt vaak gebruikt voor het vrijgeven van middelen (bestanden, mutexen, verbindingen).

Een bijzonderheid is dat alle argumenten van de functies die in defer zijn doorgegeven, onmiddellijk bij de verklaring worden berekend en niet tijdens de uitvoering.

func test() { for i := 0; i < 3; i++ { defer fmt.Println(i) // Print: 2, 1, 0 } }

Vraag met een val.

Wat geeft de volgende code als uitvoer?

func main() { for i := 0; i < 3; i++ { defer fmt.Println(i) } }

Antwoord:

Dit zal het volgende printen:

2
1
0

Omdat bij elke cyclus het argument i onmiddellijk wordt berekend (op het moment van defer), en alle waarden in de defer-stack worden opgeslagen.

Voorbeelden van echte fouten door onbekendheid met de details van het onderwerp.


Verhaal

In een bestandservice vergaten ze te controleren dat defer alleen wordt aangeroepen bij een normale uitgang uit de functie. Er waren lekken als het programma onverwacht beëindigde vóór het aanroepen van defer.


Verhaal

In een data pipeline was er een vergetelheid — in de lus gebruikten ze defer voor het sluiten van connecties, maar feitelijk werden deze pas gesloten na de voltooiing van de hele functie, en niet na elke iteratie. Dit leidde tot uitputting van middelen.


Verhaal

In de logger gebruikten ze defer met een anonieme functie, in de veronderstelling dat het argument tijdens de aanroep werd berekend. Hierdoor bevatte de log op het einde verouderde informatie, omdat de waarden eerder werden vastgelegd.