panic, recover e defer
Quando utilizzare panic e come recuperare in modo corretto
panic, recover e defer è una lezione Go Academy gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Go Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Go Academy include 4 lezioni in totale.
Che cos'è panic?
panic interrompe l'esecuzione normale della goroutine corrente, svolge lo stack delle chiamate eseguendo le funzioni differite e causa il crash del programma se non viene recuperato:
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!
}Quando utilizzare panic
Utilizzi panic solo per:
- Errori del programmatore realmente irrecuperabili (invarianti violate)
- Condizioni impossibili che indicano un bug
- Problemi all'avvio (configurazione mancante, connessioni non riuscite durante l'inizializzazione)
Non utilizzi mai panic per condizioni di errore previste: utilizzi invece error.
Nozioni di base su defer
defer programma una chiamata di funzione da eseguire quando la funzione circostante restituisce il controllo, indipendentemente da come lo restituisce (normalmente, con un errore o a causa di un 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 per la pulizia
L'uso più comune di defer consiste nel garantire la pulizia delle risorse:
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 — Intercettare i panic
recover interrompe un panic e restituisce il valore del panic. Deve essere chiamato direttamente all'interno di una funzione defer:
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 deve trovarsi in una funzione differita
recover funziona solo se viene chiamato direttamente all'interno di una funzione differita. Se viene chiamato altrove, restituisce nil:
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() }Panic nel codice delle librerie
Il codice delle librerie non dovrebbe quasi mai lasciare che i panic raggiungano i chiamanti. Converta i panic in errori al confine:
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
}Ordine LIFO di defer e problema nei cicli
Le chiamate differite vengono eseguite in ordine last-in, first-out (LIFO). Faccia attenzione a posticipare chiamate all'interno dei cicli: utilizzi una closure o una funzione di supporto:
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 con valori restituiti denominati
Le funzioni differite possono leggere e modificare i valori restituiti denominati; ciò è utile per annotare gli errori:
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 e error: guida alla scelta
Scelta tra panic ed error:
- Utilizzi error per gli errori previsti (file non trovato, timeout di rete, input non valido)
- Utilizzi panic per gli errori di programmazione (accesso a una mappa nil, indice fuori dai limiti), gli stati impossibili e gli errori di inizializzazione
- Non utilizzi mai panic oltre i confini di un'API: i chiamanti non possono gestirlo
- Nei server, recuperi i panic al livello superiore della goroutine per evitare i crash
Verifica rapida
Dove deve essere chiamato recover() per intercettare un panic?
Riepilogo: panic, recover, defer
Riepilogo:
panic: risale lo stack, esegue i defer e causa il crash se non viene recuperatodefer: viene eseguito all'uscita dalla funzione (in caso di esecuzione normale, errore o panic), in ordine LIFOrecover: interrompe il panic e restituisce un valore; deve trovarsi in undefer- Usi panic per gli errori di programmazione, non per i fallimenti previsti
- Converti i panic in errori ai confini dell'API
Impara Go con un tutor IA — gratis
Scrivi ed esegui vero codice nel tuo browser, ricevi aiuto istantaneo da un tutor IA disponibile 24/7, e riprendi da dove hai lasciato sul web o nell'app.
- Corsi
- 51
- Lezioni
- 203
Domande Frequenti
La lezione «panic, recover e defer» è gratuita?
Sì — il testo completo di «panic, recover e defer» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Go Academy, passa a CoddyKit PRO. Il corso Go Academy include 4 lezioni in totale.
Cosa imparerò in «panic, recover e defer»?
Quando utilizzare panic e come recuperare in modo corretto Eserciti Go Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Go Academy?
Non è richiesta alcuna esperienza precedente. Go Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.
Quanto tempo richiede la lezione «panic, recover e defer»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Go Academy?
Sì. Ogni lezione Go Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- L'interfaccia error
- Creare errori personalizzati
- Wrapping e unwrap degli errori
- panic, recover e defer