ProgrammazioneSenior Go Developer

Racconta come Go implementa le funzioni integrate recover e panic. Qual è l'ordine corretto per il loro utilizzo per un recupero sicuro in goroutine?

Supera i colloqui con l'assistente IA Hintsage

Risposta

In Go, la panico (panic) è usata per segnalare un errore fatale nel programma. Dopo una chiamata a panic, l'esecuzione inizia con l'unwind dello stack e la chiamata a tutte le funzioni deferred. Se nello stack c'è una funzione con una chiamata a recover(), può intercettare e gestire la panico — ma recover funziona solo all'interno della propria goroutine e solo quando chiamato da defer.

Il pattern raccomandato per un recupero sicuro è:

func safe(fn func()) { defer func() { if r := recover(); r != nil { fmt.Println("Recuperato da panic:", r) } }() fn() } go safe(func() { panic("fail!") // non porta all'arresto del programma })

È importante ricordare che:

  • panic interrompe l'esecuzione della goroutine corrente fino al primo recover
  • Recover funziona solo se chiamato da defer all'interno della stessa goroutine
  • Se recover non è utilizzato, la panico porterà all'interruzione dell'intero programma

Domanda trabocchetto

Può recover intercettare una panico avvenuta in un'altra goroutine?

Risposta: No, recover funziona solo all'interno della goroutine in cui è avvenuta la panico, e solo se chiamato in una funzione deferred. Se la panico si verifica in una goroutine e recover è chiamato in un'altra, non avverrà alcuna intercettazione, il programma si arresta in modo anomalo.

Esempio:

func main() { go func() { panic("dentro la goroutine") }() time.Sleep(time.Second) recover() // Non funzionerà! Panic chiuderà il programma }

Esempi di errori reali a causa della scarsa comprensione dell'argomento


Storia

Uno sviluppatore ha implementato la gestione degli errori usando il pattern defer recover() solo nella funzione principale. Quando si è verificata una panico all'interno di un worker in una goroutine separata, l'intero programma è andato in crash — l'errore non è stato intercettato dal recover globale.


Storia

Nel progetto è stato utilizzato defer/recover per un arresto controllato del server web, ritenendo che fosse sufficiente. Si è scoperto che una panico in una delle goroutine logiche terminava l'intero processo, perché la gestione del recover era nel posto sbagliato — è stato necessario rifattorizzare l'intero pool di worker.


Storia

Nel processo di gestione dei messaggi si è verificata una panico a causa di un malfunzionamento della funzione user. Lo sviluppatore si aspettava che fosse "catturata" dal recover di alto livello, ma non si era reso conto che recover funziona SOLO da defer. Di conseguenza, il servizio è andato in crash in modo irregolare quando un messaggio non valido appariva nella coda.