ProgrammatieSenior Go Developer

Vertel hoe Go de ingebouwde functies recover en panic implementeert. Wat is de juiste volgorde van gebruik voor een veilige herstel in een goroutine?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord

In Go wordt panic gebruikt om aan te geven dat er een fatale fout in het programma is. Na het aanroepen van panic begint de uitvoering met het unwinden van de stack en het aanroepen van alle deferred-functies. Als er in de stack een functie is met een aanroep van recover(), kan deze de panic opvangen en verwerken — maar recover werkt alleen binnen zijn eigen goroutine en alleen wanneer deze vanuit defer wordt aangeroepen.

De aanbevolen patroon voor veilig herstel:

func safe(fn func()) { defer func() { if r := recover(); r != nil { fmt.Println("Hersteld van panic:", r) } }() fn() } go safe(func() { panic("fail!") // stopt het programma niet })

Het is belangrijk om te onthouden dat:

  • panic beëindigt de uitvoering van de huidige goroutine tot aan de eerste recover
  • Recover werkt alleen wanneer deze wordt aangeroepen vanuit defer binnen dezelfde goroutine
  • Als recover niet wordt gebruikt, zal een panic leiden tot het beëindigen van het gehele programma

Vraag met een valkuil

Kan recover een panic opvangen die in een andere goroutine is opgetreden?

Antwoord: Nee, recover werkt alleen binnen de goroutine waar de panic heeft plaatsgevonden, en alleen als het is aangeroepen in een deferred functie. Als de panic in de ene goroutine is opgetreden en recover wordt in een andere aangeroepen, zal er geen opvangen plaatsvinden en zal het programma crashen.

Voorbeeld:

func main() { go func() { panic("binnen goroutine") }() time.Sleep(time.Second) recover() // Werkt niet! Panic beëindigt het programma }

Voorbeelden van echte fouten als gevolg van onwetendheid over de nuances van het onderwerp


Verhaal

Een ontwikkelaar implementeerde foutafhandelings met behulp van het patroon defer recover() alleen in de hoofdfunctie. Toen er een panic optrad binnen een worker in een aparte goroutine, crashte het hele programma omdat de fout niet werd opgevangen door de globale recover.


Verhaal

In een project werd defer/recover gebruikt voor een gracefull shutdown van de webserver, in de veronderstelling dat dit voldoende was. Het bleek dat een panic in een van de goroutines de hele process beëindigde, omdat de verwerking van recover niet op de juiste plaats stond — het was nodig om de gehele worker pool opnieuw te ontwerpen.


Verhaal

In de berichtverwerkingsstroom ontstond een panic vanwege een fout in de gebruikersfunctie. De ontwikkelaar verwachtte dat deze zou worden "opgevangen" door de bovenliggende recover, maar realiseerde zich niet dat recover ALLEEN werkt vanuit defer. Als gevolg hiervan crashte de service onregelmatig wanneer er een onjuist bericht in de wachtrij verscheen.