panic, recover und defer
Wann Sie panic verwenden und wie Sie Fehler elegant abfangen
panic, recover und defer ist eine kostenlose Go Academy-Lektion auf CoddyKit. Dies ist Lektion 4 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Go Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Go Academy-Kurs umfasst insgesamt 4 Lektionen.
Was ist panic?
panic beendet die normale Ausführung der aktuellen Goroutine, wickelt den Call Stack ab und führt dabei aufgeschobene Funktionen aus. Wenn der Panic nicht abgefangen wird, stürzt das Programm ab:
package main
import "fmt"
func mustPositive(n int) int {
if n <= 0 {
panic(fmt.Sprintf("mustPositive: got %d", n))
}
return n
}
func main() {
fmt.Println(mustPositive(5)) // 5
// fmt.Println(mustPositive(-1)) // panics!
}Wann panic verwendet wird
Verwenden Sie panic nur für:
- Wirklich nicht behebbare Programmierfehler (verletzte Invarianten)
- Unmögliche Bedingungen, die auf einen Bug hindeuten
- Fehler beim Start (fehlende Konfiguration, fehlgeschlagene Verbindungen während der Initialisierung)
Verwenden Sie panic niemals für erwartete Fehlerbedingungen — verwenden Sie stattdessen error.
Grundlagen von defer
defer plant einen Funktionsaufruf für den Zeitpunkt ein, an dem die umgebende Funktion zurückkehrt — unabhängig davon, wie sie zurückkehrt (normal, mit Fehler oder durch einen Panic):
package main
import "fmt"
func main() {
defer fmt.Println("third")
defer fmt.Println("second") // LIFO order
defer fmt.Println("first")
fmt.Println("running...")
// Output:
// running...
// first
// second
// third
}defer zur Bereinigung
Der häufigste Anwendungsfall für defer ist die zuverlässige Bereinigung von Ressourcen:
package main
import ("fmt"; "os")
func readFile(path string) (string, error) {
f, err := os.Open(path)
if err != nil {
return "", fmt.Errorf("open: %w", err)
}
defer f.Close() // always runs, even if we return early
buf := make([]byte, 1024)
n, _ := f.Read(buf)
return string(buf[:n]), nil
}recover — Panics abfangen
recover beendet einen Panic und gibt den Panic-Wert zurück. Es muss direkt innerhalb einer defer-Funktion aufgerufen werden:
package main
import "fmt"
func safeDiv(a, b int) (result int, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("recovered from panic: %v", r)
}
}()
return a / b, nil // panics if b==0
}
func main() {
r, err := safeDiv(10, 0)
fmt.Println(r, err)
// 0 recovered from panic: runtime error: integer divide by zero
}recover muss in einer Deferred-Funktion stehen
recover funktioniert nur, wenn es direkt innerhalb einer Deferred-Funktion aufgerufen wird. Bei einem Aufruf an anderer Stelle wird nil zurückgegeben:
package main
import "fmt"
func wrong() {
// recover() here does nothing — not in defer
}
func correct() {
defer func() {
if r := recover(); r != nil {
fmt.Println("caught:", r)
}
}()
panic("oops")
}
func main() { correct() }Panics in Bibliothekscode
Bibliothekscode sollte Panics fast nie bis zu den Aufrufern durchdringen lassen. Wandeln Sie Panics an der Grenze in Fehler um:
package main
import ("fmt"; "runtime/debug")
func safeCall(fn func()) (err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("panic: %v\n%s", r, debug.Stack())
}
}()
fn()
return nil
}
func main() {
err := safeCall(func() { panic("boom") })
fmt.Println(err != nil) // true
}LIFO-Reihenfolge von defer und Fallstrick in Schleifen
Aufgeschobene Aufrufe werden in Last-in-first-out-Reihenfolge (LIFO) ausgeführt. Seien Sie vorsichtig, wenn Sie defer innerhalb von Schleifen verwenden — nutzen Sie eine Closure oder Hilfsfunktion:
package main
import "fmt"
func processFiles(names []string) {
for _, name := range names {
name := name // capture loop variable
defer func() { fmt.Println("close:", name) }()
}
}
func main() {
processFiles([]string{"a.txt", "b.txt", "c.txt"})
// Output (LIFO): close: c.txt, close: b.txt, close: a.txt
}defer mit benannten Rückgabewerten
Deferred-Funktionen können benannte Rückgabewerte lesen und ändern — dies ist nützlich, um Fehler zu annotieren:
package main
import "fmt"
func doWork() (err error) {
defer func() {
if err != nil {
err = fmt.Errorf("doWork: %w", err)
}
}()
return fmt.Errorf("something failed")
}
func main() {
err := doWork()
fmt.Println(err) // doWork: something failed
}panic vs. error: Entscheidungshilfe
Zwischen panic und error wählen:
- Verwenden Sie error: erwartete Fehler (Datei nicht gefunden, Netzwerk-Timeout, ungültige Eingabe)
- Verwenden Sie panic: Programmierfehler (Zugriff auf eine nil-Map, Index außerhalb des gültigen Bereichs), unmögliche Zustände und Fehler bei der Initialisierung
- Verwenden Sie panic niemals über API-Grenzen hinweg — Aufrufer können damit nicht umgehen
- Fangen Sie Panics auf der obersten Ebene einer Goroutine in Servern ab, um Abstürze zu vermeiden
Schnelltest
Wo muss recover() aufgerufen werden, um einen Panic abzufangen?
Zusammenfassung: panic, recover, defer
Zusammenfassung:
panic: entrollt den Stack, führtdefer-Anweisungen aus und lässt das Programm abstürzen, wenn die Panic nicht abgefangen wirddefer: wird beim Verlassen einer Funktion ausgeführt (normal, bei einem Fehler oder einer Panic); in LIFO-Reihenfolgerecover: beendet die Panic und gibt den Wert zurück; muss indeferverwendet werden- Verwenden Sie Panic für Programmierfehler, nicht für erwartete Fehler
- Wandeln Sie Panics an API-Grenzen in Fehler um
Häufig gestellte Fragen
Ist die Lektion „panic, recover und defer“ kostenlos?
Ja — der vollständige Text von „panic, recover und defer“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Go Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Go Academy-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „panic, recover und defer“?
Wann Sie panic verwenden und wie Sie Fehler elegant abfangen Du übst Go Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um Go Academy zu starten?
Keine Vorkenntnisse erforderlich. Go Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 4 von 4.
Wie lange dauert die Lektion „panic, recover und defer“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser Go Academy-Lektion Code schreiben und ausführen?
Ja. Jede Go Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Das error-Interface
- Eigene Fehler erstellen
- Fehler-Wrapping und -Unwrapping
- panic, recover und defer