0Pricing
Go Academy · Pelajaran

panic, recover, dan defer

Kapan menggunakan panic dan cara memulihkan eksekusi dengan baik

panic, recover, dan defer adalah pelajaran Go Academy gratis di CoddyKit. Ini adalah pelajaran 4 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Go Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Go Academy mencakup 4 pelajaran total.

Apa Itu panic?

panic menghentikan eksekusi normal goroutine saat ini, mengurai tumpukan pemanggilan sambil menjalankan fungsi yang ditunda, dan menghentikan program jika tidak dipulihkan:

package main
import "fmt"

func mustPositive(n int) int {
    if n <= 0 {
        panic(fmt.Sprintf("mustPositive: got %d", n))
    }
    return n
}

func main() {
    fmt.Println(mustPositive(5))  // 5
    // fmt.Println(mustPositive(-1)) // panics!
}

Kapan Menggunakan panic

Gunakan panic hanya untuk:

  • Kesalahan pemrogram yang benar-benar tidak dapat dipulihkan (invarian yang rusak)
  • Kondisi mustahil yang menunjukkan adanya bug
  • Kegagalan saat memulai (konfigurasi tidak ada, koneksi gagal selama inisialisasi)

Jangan pernah menggunakan panic untuk kondisi kegagalan yang diperkirakan — gunakan error sebagai gantinya.

Dasar-Dasar defer

defer menjadwalkan pemanggilan fungsi untuk dijalankan saat fungsi yang menaunginya mengembalikan nilai, terlepas dari cara fungsi tersebut selesai (normal, galat, atau panic):

package main
import "fmt"

func main() {
    defer fmt.Println("third")
    defer fmt.Println("second")  // LIFO order
    defer fmt.Println("first")
    fmt.Println("running...")
    // Output:
    // running...
    // first
    // second
    // third
}

defer untuk Pembersihan

Penggunaan defer yang paling umum adalah memastikan sumber daya dibersihkan:

package main
import ("fmt"; "os")

func readFile(path string) (string, error) {
    f, err := os.Open(path)
    if err != nil {
        return "", fmt.Errorf("open: %w", err)
    }
    defer f.Close()  // always runs, even if we return early

    buf := make([]byte, 1024)
    n, _ := f.Read(buf)
    return string(buf[:n]), nil
}

recover — Menangkap panic

recover menghentikan panic dan mengembalikan nilai panic. Fungsi ini harus dipanggil langsung di dalam fungsi defer:

package main
import "fmt"

func safeDiv(a, b int) (result int, err error) {
    defer func() {
        if r := recover(); r != nil {
            err = fmt.Errorf("recovered from panic: %v", r)
        }
    }()
    return a / b, nil  // panics if b==0
}

func main() {
    r, err := safeDiv(10, 0)
    fmt.Println(r, err)
    // 0 recovered from panic: runtime error: integer divide by zero
}

recover Harus Berada dalam Fungsi yang Ditunda

recover hanya berfungsi jika dipanggil langsung di dalam fungsi yang ditunda. Jika dipanggil di tempat lain, fungsi ini mengembalikan nil:

package main
import "fmt"

func wrong() {
    // recover() here does nothing — not in defer
}

func correct() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("caught:", r)
        }
    }()
    panic("oops")
}

func main() { correct() }

panic dalam Kode Pustaka

Kode pustaka hampir tidak boleh membiarkan panic keluar ke pemanggil. Ubah panic menjadi galat di batas:

package main
import ("fmt"; "runtime/debug")

func safeCall(fn func()) (err error) {
    defer func() {
        if r := recover(); r != nil {
            err = fmt.Errorf("panic: %v\n%s", r, debug.Stack())
        }
    }()
    fn()
    return nil
}

func main() {
    err := safeCall(func() { panic("boom") })
    fmt.Println(err != nil) // true
}

Urutan LIFO defer dan Kesalahan dalam Perulangan

Pemanggilan yang ditunda dijalankan dalam urutan masuk terakhir, keluar pertama (LIFO). Berhati-hatilah saat menunda pemanggilan di dalam perulangan — gunakan closure atau fungsi pembantu:

package main
import "fmt"

func processFiles(names []string) {
    for _, name := range names {
        name := name  // capture loop variable
        defer func() { fmt.Println("close:", name) }()
    }
}

func main() {
    processFiles([]string{"a.txt", "b.txt", "c.txt"})
    // Output (LIFO): close: c.txt, close: b.txt, close: a.txt
}

defer dengan Nilai Kembalian Bernama

Fungsi yang ditunda dapat membaca dan mengubah nilai kembalian bernama — berguna untuk memberi anotasi pada galat:

package main
import "fmt"

func doWork() (err error) {
    defer func() {
        if err != nil {
            err = fmt.Errorf("doWork: %w", err)
        }
    }()
    return fmt.Errorf("something failed")
}

func main() {
    err := doWork()
    fmt.Println(err) // doWork: something failed
}

panic vs Galat: Panduan Keputusan

Memilih antara panic dan galat:

  • Gunakan galat: kegagalan yang diperkirakan (berkas tidak ditemukan, waktu tunggu jaringan habis, masukan tidak valid)
  • Gunakan panic: kesalahan pemrograman (akses map nil, akses di luar batas), keadaan mustahil, kegagalan inisialisasi
  • Jangan pernah menggunakan panic melintasi batas API — pemanggil tidak dapat menanganinya
  • Pulihkan panic di tingkat teratas goroutine pada server untuk mencegah penghentian program

Pemeriksaan Singkat

Di mana recover() harus dipanggil untuk menangkap panic?

Ringkasan: panic, recover, defer

Ringkasan:

  • panic: mengurai tumpukan, menjalankan penundaan, dan menyebabkan program berhenti jika tidak dipulihkan
  • defer: dijalankan saat fungsi keluar (secara normal, karena galat, atau karena panic); dalam urutan LIFO
  • recover: menghentikan panic dan mengembalikan nilai; harus berada dalam defer
  • Gunakan panic untuk galat pemrogram, bukan kegagalan yang diperkirakan
  • Ubah panic menjadi galat di batas API

Pertanyaan yang Sering Diajukan

Apakah pelajaran “panic, recover, dan defer” gratis?

Ya — teks lengkap “panic, recover, dan defer” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Go Academy, upgrade ke CoddyKit PRO. Kursus Go Academy mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “panic, recover, dan defer”?

Kapan menggunakan panic dan cara memulihkan eksekusi dengan baik Kamu berlatih Go Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai Go Academy?

Tidak diperlukan pengalaman sebelumnya. Go Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 4 dari 4.

Berapa lama pelajaran “panic, recover, dan defer” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran Go Academy ini?

Ya. Setiap pelajaran Go Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Interface error
  2. Membuat Error Khusus
  3. Pembungkusan dan Pelepasan Error
  4. panic, recover, dan defer
← Kembali ke Go Academy