Te trzy słowa kluczowe obsługują odroczoną wykonywanie i wyjątkowe sytuacje. defer zaplanuje oczyszczanie, panic wyzwala awarię uruchomieniową (dla naprawdę wyjątkowych przypadków), a recover może złapać panic, aby zapobiec awarii programu.
Te trzy słowa kluczowe obsługują odroczoną wykonywanie i wyjątkowe sytuacje. defer zaplanuje oczyszczanie, panic wyzwala awarię uruchomieniową (dla naprawdę wyjątkowych przypadków), a recover może złapać panic, aby zapobiec awarii programu.
defer to niezbędna, idiomatyczna funkcja Go do gwarantowanego oczyszczania — umieszczenie zwalniania zasobów tuż obok pozyskania i zapewnienie, że zostanie wykonane na każdej ścieżce powrotu (včetně paniki), co zapobiega wyciekom plików, blokad i połączeń znacznie bardziej niezawodnie niż ręczne oczyszczanie.
Zrozumienie jego porządku LIFO jest również ważne. panic/recover zapewniają mechanizm przypominający wyjątki, ale krytyczna zasada polega na tym, że Go zarezerwowuje je dla naprawdę wyjątkowych, nieodwracalnych sytuacji — normalne błędy powinny zawsze być zwracane jako wartości i sprawdzane.
Niewłaściwe użycie panic/recover jako ogólnej obsługi wyjątków jest nieidiomatyczne i częstym błędem dla programistów przychodzących z języków opartych na wyjątkach.
Wiedzenie, kiedy używać defer (zawsze, do oczyszczania), zwracania error (zwykłe błędy) i panic/recover (rzadko, wyjątkowo lub na granicach) jest fundamentalne dla pisania poprawnego, idiomatycznego Go i jest częstym tematem rozmów kwalifikacyjnych.
func readFile() error {
f, err := os.Open("file.txt")
if err != nil { return err }
defer f.Close() // GUARANTEED to run when readFile returns (any path)
// ... use f, with multiple return points ...
return nil // f.Close() runs here automatically
}
defer planuje wywołanie funkcji na wykonanie, gdy otaczająca funkcja się zwraca — niezależnie od tego, jak się zwraca (normalny powrót, błąd lub panic). To idiomatyczny sposób zapewnienia oczyszczania: zamykania plików, odblokowywania muteksów, zamykania połączeń — umieszczone tuż obok pozyskania, aby nie można było tego zapomnieć.
defer fmt.Println("1")
defer fmt.Println("2")
defer fmt.Println("3")
// prints: 3, 2, 1 — last deferred, first executed (stack order)
func mustPositive(n int) {
if n < 0 {
panic("negative not allowed") // stops normal execution, unwinds the stack
}
}
// panic runs deferred functions as it unwinds, then crashes the program (with a stack trace)
panic zatrzymuje normalny przepływ i rozkręca stos wywołań (uruchamiając odroczone funkcje po drodze), ostatecznie powodując awarię programu. To dla błędów programisty / warunków nieodwracalnych (poza granicami, dereferencja nil, niemożliwe stany) — NIE dla zwykłych błędów (te używają zwracanych wartości error).
func safeProcess() {
defer func() {
if r := recover(); r != nil { // recover() returns the panic value
fmt.Println("recovered from:", r) // handle it; program continues
}
}()
panic("something broke") // this panic is caught by the recover above
}
// safeProcess returns normally instead of crashing
recover odzyskuje kontrolę nad paniką goroutine'a — ale działa tylko wewnątrz odroczonej funkcji. Jest używany rzadko, np. aby zatrzymać awarię pojedynczego handlera żądania w całym serwerze.
Normal/expected failures (file missing, bad input, validation) → return an error value
panic/recover → reserve for TRULY exceptional cases (bugs, unrecoverable states)
and boundaries (e.g. a server recovering so one bad request doesn't kill the process)