In Go, l'approccio standard è la gestione degli errori tramite il valore restituito error. Questo consente di controllare esplicitamente cosa fare in caso di errore in ogni punto. Panic è un meccanismo per gestire situazioni catastrofiche impreviste: interrompe l'esecuzione fino al defer più vicino, dove si può usare recover per "salvare". Tuttavia, recover funziona solo all'interno di defer.
Migliori pratiche:
func safeDivide(a, b int) (int, error) { if b == 0 { return 0, errors.New("divide by zero") } return a/b, nil } func mustDivide(a, b int) int { if b == 0 { panic("divide by zero!") } return a/b }
È possibile "catturare" qualsiasi errore di panico con recover in qualsiasi parte del programma?
Risposta: No, recover funzionerà solo all'interno di defer e solo nella stessa goroutine in cui è stato chiamato panic. Negli altri casi, panic terminerà l'esecuzione di questa (o di tutte) le goroutine — questo spesso risulta essere una sorpresa.
Storia
Nell'API REST si utilizzava panic per gestire errori normali nella logica di business. Questo ha portato a crash imprevisti dell'applicazione e log non corretti, poiché recover non funzionava sempre correttamente.
Storia
Nel servizio di elaborazione dei pagamenti è stata implementata defer + recover nella funzione principale, per "catturare" tutti i panic, ma si è dimenticati delle goroutine — nelle goroutine figlie, senza defer/recover, l'applicazione è crollata con errori "terribili", lasciando parte delle transazioni in uno stato incoerente.
Storia
Nel parser di strutture complesse si è dimenticato di restituire l'errore, sostituendolo con panic — questo ha complicato la manutenzione e il testing, costringendo a riscrivere completamente la gestione degli errori per avere un logging dettagliato e una UX corretta.