Pelajaran modul (5/5)
`defer`: jaminan pembersihan
defer menunda pelaksanaan panggilan hingga fungsi penutup
kembali. It runs even if the function exits via panic. Multiple defers
dalam fungsi yang sama dijalankan dalam urutan LIFO (Masuk Terakhir, Keluar Pertama).
Ini adalah mekanisme idiomatis untuk pembersihan sumber daya: menutup file, membuka kunci mutex, melepaskan koneksi, memulihkan status.
Sintaks dan kasus penggunaan kanonik
f, err := os.Open(path)
if err != nil {
return err
}
defer f.Close() // chiamata SEMPRE all'uscita della funzione
// ... usa f liberamente ...
return nilKhas: f.Close(), mu.Unlock(), db.Close(), tx.Rollback(),
recover().
Argumen segera dievaluasi, eksekusi ditunda
Saat Anda menulis defer foo(x), x dievaluasi pada saat
defer, not at execution time:
x := 10
defer fmt.Println(x) // cattura 10
x = 99
// quando la funzione ritorna stampa "10", non "99"pesanan LIFO
Defers menumpuk dan mengeksekusi dimulai dengan yang terbaru:
defer fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)
// output: 3, 2, 1Hal ini konsisten dengan semantik sumber daya: yang terakhir dibuka adalah yang pertama untuk ditutup.
defer + recover : menangani kepanikan
defer adalah satu-satunya cara untuk mencegat panic:
func safe() {
defer func() {
if r := recover(); r != nil {
fmt.Println("recuperato:", r)
}
}()
panic("boom")
}Kesalahan: defer dalam satu lingkaran
Menempatkan defer f.Close() dalam satu lingkaran akan terakumulasi penundaan hingga akhir
the function, not of each iteration. In a long loop you open many files
dan hanya menutupnya ketika fungsinya keluar: risiko kebocoran deskriptor file.
// MALE: defer accumulati
for _, path := range paths {
f, _ := os.Open(path)
defer f.Close() // chiude TUTTI alla fine della funzione esterna
// ...
}
// MEGLIO: estrai in una funzione
for _, path := range paths {
elabora(path) // ogni chiamata ha il proprio scope di defer
}Cobalah
Cetak 'inizio', lalu tunda cetak 'fine' dengan defer, lalu cetak 'mezzo'. Outputnya harus: inizio / mezzo / fine.
Tunjukkan petunjuk
Penundaan berjalan ketika main() akan kembali.
Solusi tersedia setelah 3 upaya
Tulis tiga penundaan berturut-turut yang mencetak 1, 2 dan 3 sesuai urutan kode. Outputnya akan menjadi 3/2/1 (LIFO).
Tunjukkan petunjuk
Tiga penundaan secara berurutan; ingat mereka mengeksekusi dalam urutan terbalik.
Solusi tersedia setelah 3 upaya
Apa yang dicetak ini? (catatan: argumen penangguhan segera dievaluasi)
x := 10
defer fmt.Println(x)
x = 99Rekap
defer call()menunda eksekusi hingga fungsinya kembali.- Multiple defers = LIFO order.
- Argumen segera dievaluasi, eksekusi ditunda.
- Digunakan untuk pembersihan deterministik: file, mutex, koneksi.
defer+recover()mencegatpanic(jarang, di perbatasan).- Jangan pernah
deferdi dalam loop panjang: ini terakumulasi hingga fungsi luar kembali.