In Go is de standaardbenadering het afhandelen van fouten via de geretourneerde waarde error. Dit stelt ons in staat om expliciet te controleren wat te doen in geval van een fout op elk punt. Panic is een mechanisme voor het omgaan met onvoorziene catastrofale situaties: het onderbreekt de uitvoering tot de dichtstbijzijnde defer, waar recover kan worden gebruikt om "redding" te bieden. Maar recover werkt alleen binnen defer.
Beste praktijken:
func safeDivide(a, b int) (int, error) { if b == 0 { return 0, errors.New("delen door nul") } return a/b, nil } func mustDivide(a, b int) int { if b == 0 { panic("delen door nul!") } return a/b }
Kun je "iedere" panicfout vangen met recover op eender welk punt in het programma?
Antwoord: Nee, recover werkt alleen binnen defer en alleen in dezelfde goroutine waar de panic is aangeroepen. In andere gevallen zal de panic de uitvoering van deze (of alle) goroutines beëindigen — wat vaak een verrassing is.
Verhaal
In de REST API werd panic gebruikt voor het afhandelen van normale fouten in de bedrijfslogica. Dit leidde tot onvoorspelbare crashes van de applicatie en onjuiste logs, omdat recover niet altijd correct werkte.
Verhaal
In de betalingsverwerkingsservice werd defer + recover geïmplementeerd in de hoofdfunctie om "alle" panics te "vangen", maar men vergat de goroutines — in de kindgoroutines zonder defer/recover viel de applicatie met "angstaanjagende" fouten, waardoor een deel van de transacties in een inconsistente toestand bleef.
Verhaal
In de parser voor complexe structuren vergat men de fout terug te geven, verving deze door panic — dit bemoeilijkte onderhoud en testen, waardoor het nodig was om de foutafhandeling volledig opnieuw te schrijven voor gedetailleerde logging en een correcte UX.