Geschichte der Frage:
Die Operatoren defer, panic und recover sind wichtige Mechanismen zur Steuerung des Programmablaufs in Go. Der Operator defer wird für die verzögerte Ausführung von Funktionen verwendet, panic initiiert einen Fehler (Notabschaltung), und recover ermöglicht es, den Notfall abzufangen und die Ausführung fortzusetzen.
Problem:
Ohne eine richtige Verwendung dieser Mittel ist es schwierig, Ressourcen korrekt zu finalisieren und Fehlertoleranz zu realisieren. Unvorhersehbares Beenden einer Funktion, nicht freigegebene Ressourcen und unkontrollierter "Ausgang" der Anwendung bei Fehlern sind häufige Probleme bei falschem Ansatz.
Lösung:
Die richtige Anwendung von defer stellt die sichere Freigabe von Ressourcen auch bei Fehlern sicher. panic ist ein Mechanismus für die Notabschaltung bei unvorhergesehenen Situationen, der nur für wirklich außergewöhnliche Fälle verwendet werden sollte. recover gibt die Möglichkeit, die Ausführung innerhalb einer verzögerten Funktion "zu retten".
Beispielcode:
func riskyFunction() { defer func() { if r := recover(); r != nil { fmt.Println("In riskyFunction wiederhergestellt:", r) } }() fmt.Println("Einige Arbeiten verrichten...") panic("etwas Schlimmes ist passiert!") } func main() { riskyFunction() fmt.Println("Nach riskyFunction") }
Wesentliche Merkmale:
defer wird immer in umgekehrter Reihenfolge bis zum Verlassen der Funktion aufgerufen. Auch bei panic.recover funktioniert NUR innerhalb verzögerter Funktionen.panic unterbricht die Ausführung der aktuellen Goroutine; wenn es nicht über recover abgefangen wird - beendet es den Prozess.Warum funktioniert recover nicht außerhalb von defer innerhalb der gleichen Funktion, in der panic aufgetreten ist?
recover gibt ein nicht nullwertiges Ergebnis zurück (d.h. es fängt die Panik ab), nur wenn es aus einer deferred-Funktion aufgerufen wird, die innerhalb derselben Funktion eingebettet ist, in der die panic aufgetreten ist. Wird recover direkt aufgerufen, gibt es immer nil zurück.
Beispielcode:
func f() { panic("fehler!") r := recover() // funktioniert nicht! }
Kann man defer nach einer panic aufrufen und wird es ausgeführt?
Nein. Nach einer panic werden alle bereits registrierten defer-Aufrufe ausgeführt, aber neue defer nach panic werden nicht mehr aufgerufen, da die Ausführung der Funktion bereits "zusammengeklappt" ist.
Kann man sich (recover) von einer panic erholen, die in einer anderen Goroutine aufgetreten ist?
Nein, recover funktioniert nur für Panik in der aktuellen Goroutine. Wenn eine andere Goroutine panikt und der Aufruf von recover nicht in dieser gleichen Goroutine erfolgt - wird die Anwendung beendet.
Im Projekt wurden alle Fehler über panic ausgelöst, und die Verarbeitung des recover war nur in der Hauptfunktion. Dies führte dazu, dass Ressourcen nicht geschlossen wurden, Daten verloren gingen, und die Logs waren unleserlich.
Vorteile:
Nachteile:
In jedem kritischen Abschnitt wurde defer zur Freigabe von Ressourcen verwendet, panic wurde nur für wirklich außergewöhnliche Situationen verwendet, und recover wurde zur Isolierung von Notfällen in nicht kritischen Teilen eingesetzt. Gleichzeitig wurden alle Fehlerelemente protokolliert.
Vorteile:
Nachteile: