La parola chiave defer in Go ritarda l'esecuzione delle funzioni specificate fino all'uscita dalla funzione circostante: le funzioni si accumulano nello stack e vengono eseguite in ordine inverso (LIFO). Questo viene spesso utilizzato per liberare risorse (file, mutex, connessioni).
Una caratteristica è che tutti gli argomenti delle funzioni passate a defer vengono calcolati immediatamente al momento della dichiarazione, e non durante l'esecuzione.
func test() { for i := 0; i < 3; i++ { defer fmt.Println(i) // Stamperà: 2, 1, 0 } }
Cosa stamperà il seguente codice?
func main() { for i := 0; i < 3; i++ { defer fmt.Println(i) } }
Risposta:
Questo stamperà:
2
1
0
Perché in ogni ciclo l'argomento i viene calcolato immediatamente (al momento di defer), e tutti i valori vengono memorizzati nello stack dei defer.
Storia
In un servizio file hanno dimenticato di considerare che defer viene chiamato solo durante l'uscita normale dalla funzione. Ci sono state perdite se il programma è terminato in modo anomalo prima del punto di chiamata defer.
Storia
In una pipeline di dati si è dimenticato — nel ciclo si utilizzava defer per chiudere le connessioni, ma di fatto si chiudevano solo dopo il completamento dell'intera funzione, e non dopo ogni iterazione. Questo ha portato all'esaurimento delle risorse.
Storia
Nel logger si utilizzava defer con una funzione anonima, aspettandosi che l'argomento venisse calcolato al momento della chiamata. Di conseguenza, il log alla fine conteneva informazioni obsolete, poiché i valori venivano catturati prima.