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 dipulihkandefer: dijalankan saat fungsi keluar (secara normal, karena galat, atau karena panic); dalam urutan LIFOrecover: menghentikan panic dan mengembalikan nilai; harus berada dalamdefer- 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
- Interface error
- Membuat Error Khusus
- Pembungkusan dan Pelepasan Error
- panic, recover, dan defer