In Go wird Panic (panic) verwendet, um auf einen fatalen Fehler im Programm hinzuweisen. Nach dem Aufruf von Panic beginnt die Ausführung mit dem Unwind des Stacks und dem Aufruf aller Deferred-Funktionen. Wenn im Stack eine Funktion mit einem Aufruf von recover() vorhanden ist, kann sie die Panic abfangen und verarbeiten – aber Recover funktioniert nur innerhalb ihrer eigenen Goroutine und nur bei einem Aufruf aus defer.
Das empfohlene Muster für eine sichere Wiederherstellung:
func safe(fn func()) { defer func() { if r := recover(); r != nil { fmt.Println("Recovered from panic:", r) } }() fn() } go safe(func() { panic("fail!") // führt nicht zum Stoppen des Programms })
Es ist wichtig zu beachten, dass:
panic die Ausführung der aktuellen Goroutine bis zum ersten recover beendetKann recover eine Panic abfangen, die in einer anderen Goroutine aufgetreten ist?
Antwort: Nein, recover funktioniert nur innerhalb der Goroutine, in der die Panic aufgetreten ist, und nur wenn es in einer Deferred-Funktion aufgerufen wird. Wenn die Panic in einer Goroutine aufgetreten ist und recover in einer anderen aufgerufen wird – findet kein Abfangen statt, das Programm wird abrupt beendet.
Beispiel:
func main() { go func() { panic("inside goroutine") }() time.Sleep(time.Second) recover() // Wird nicht funktionieren! Panic beendet das Programm }
Geschichte
Ein Entwickler implementierte die Fehlermanagement mit dem Muster defer recover() nur in der Hauptfunktion. Als eine Panic innerhalb eines Workers in einer separaten Goroutine auftrat, wurde das gesamte Programm abrupt beendet – der Fehler wurde nicht vom globalen recover abgefangen.
Geschichte
Im Projekt wurde defer/recover für einen sanften Shutdown des Webservers verwendet, in der Annahme, dass das ausreichend sei. Es stellte sich heraus, dass eine Panic in einer der Logik-Goroutines den gesamten Prozess beendete, weil die Verarbeitung des recover nicht am richtigen Ort stand – das gesamte Worker-Pool musste refakturiert werden.
Geschichte
In einem Thread zur Nachrichtenverarbeitung trat eine Panic aufgrund einer fehlerhaften Benutzerfunktion auf. Der Entwickler erwartete, dass sie vom oberen recover „gefangen“ würde, erkannte jedoch nicht, dass recover NUR aus defer funktioniert. Infolgedessen stürzte der Dienst unregelmäßig ab, wenn eine ungültige Nachricht in der Warteschlange auftauchte.