← Kembali ke kursus
Pelajaran kursus · Go
Pelajaran 31

Defer & Exit

Jadwalkan pembersihan dan hentikan program dengan sengaja.

Pahami konsepnya

defer menjadwalkan sebuah pemanggilan untuk dijalankan tepat sebelum fungsi pulang — apa pun jalur pulangnya: return biasa, return di tengah cabang, bahkan panic. Pendaftarannya LIFO: yang didaftar terakhir dijalankan lebih dulu, seperti tumpukan piring.

Penggunaan paling khas adalah pembersihan berpasangan: buka berkas → defer tutup, kunci mutex → defer buka kunci, buka koneksi → defer putuskan. Menuliskannya berdampingan dengan pembukaannya memastikan tidak ada yang lupa, berapa pun cabang return yang berkembang di tengah fungsi.

os.Exit(kode) menghentikan program seketika dengan kode keluar (0 sukses, selainnya gagal). Penting: os.Exit TIDAK menjalankan defer yang tertunda — hanya gunakan di titik akhir yang memang final, seperti setelah flag.Parse gagal atau saat perintah CLI selesai total.

Coba contoh kode

package main

import "fmt"

func main() {
    defer fmt.Println("ketiga (defer terakhir didaftar)")
    defer fmt.Println("kedua (LIFO: defer ini lebih dulu)")
    fmt.Println("pertama (isi fungsi biasa)")
}

Isi fungsi jalan dulu ("pertama"), lalu defer dieksekusi berkebalikan urutan pendaftaran: yang didaftar belakangan ("kedua") lebih dulu daripada yang didaftar awal ("ketiga"). Sifat LIFO ini menjaga pembersihan bersarang terurai dengan benar — kunci yang terakhir dipasang dibuka pertama.

Pola buka-tutup berkas

func bacaConfig(nama string) error {
    f, err := os.Open(nama)
    if err != nil {
        return err
    }
    defer f.Close() // pasti dipanggil di SEMUA return

    // ... proses berkas di sini
    return nil
}

defer f.Close() ditulis tepat setelah os.Open sukses — dari titik itu tidak ada jalur pulang yang bisa lupa menutup berkas, berapa pun return yang ditambahkan belakangan. Tanpa defer, tiap cabang error harus menutup manual; satu saja terlewat, berkas bocor sampai program mati.

os.Exit melewati defer

func main() {
    defer fmt.Println("pembersihan") // TIDAK akan jalan

    fmt.Println("sebelum exit")
    os.Exit(1) // berhenti seketika, kode keluar 1
}

Program berhenti tepat setelah "sebelum exit" — baris defer tidak pernah tereksekusi karena os.Exit memotong seluruh alur pulang. Karena itu os.Exit hanya untuk titik final; untuk alur normal, biarkan main pulang sendiri agar defer bekerja.

Latihan singkat

Uji: daftarkan tiga defer yang mencetak `ketiga`, `kedua`, `pertama` — keluaran harus empat baris: `isi fungsi`, `ketiga`, `kedua`, `pertama`.