0Pricing
Go Academy · Lektion

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ührt defer-Anweisungen aus und lässt das Programm abstürzen, wenn die Panic nicht abgefangen wird
  • defer: wird beim Verlassen einer Funktion ausgeführt (normal, bei einem Fehler oder einer Panic); in LIFO-Reihenfolge
  • recover: beendet die Panic und gibt den Wert zurück; muss in defer verwendet 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

  1. Das error-Interface
  2. Eigene Fehler erstellen
  3. Fehler-Wrapping und -Unwrapping
  4. panic, recover und defer
← Zurück zu Go Academy