Defer, Panic & Recover
Menunda eksekusi dengan defer dan menangani kondisi fatal dengan recover.
defer
defer menunda sebuah pemanggilan function sampai function pembungkusnya selesai (baik normal maupun karena panic). Sangat cocok untuk membersihkan resource: menutup file, melepas lock, menutup koneksi.
func baca() {
f, _ := os.Open("data.txt")
defer f.Close() // dijamin dipanggil di akhir
// ... pakai f ...
}
Menulis defer tepat setelah resource dibuka membuatmu tidak lupa menutupnya.
Urutan: LIFO
Beberapa defer dijalankan terbalik (terakhir didaftarkan, pertama dijalankan):
defer fmt.Println("A")
defer fmt.Println("B")
defer fmt.Println("C")
fmt.Println("Isi")
// Isi, C, B, A
Argumen defer dihitung saat defer ditulis, bukan saat dijalankan.
panic
panic menghentikan alur normal: function berhenti, semua defer dijalankan, lalu panic naik ke pemanggilnya sampai program berhenti dengan pesan error. Panic dipakai untuk kondisi yang benar-benar tidak masuk akal (bug), mis. index di luar jangkauan atau nil pointer.
panic("sesuatu yang sangat salah")
Untuk kesalahan yang wajar (file tidak ada, input salah), jangan panic — kembalikan error (bab 19).
recover
recover() menangkap panic dan mengembalikan nilainya. Ia hanya bekerja di dalam function yang di-defer.
func aman() {
defer func() {
if r := recover(); r != nil {
fmt.Println("pulih:", r)
}
}()
panic("boom")
}
func main() {
aman()
fmt.Println("lanjut") // tetap jalan
}
Hasil: pulih: boom lalu lanjut. Tanpa recover, program akan mati di baris panic.
Pola umum
Library atau server sering memakai recover di lapisan terluar agar satu permintaan yang bermasalah tidak menjatuhkan seluruh server.