Panic, Defer, dan Recover
Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan GO di Coddy. Pelajaran 57 dari 107.
Meskipun Go menekankan pengembalian error, beberapa situasi memang tidak dapat dipulihkan. Untuk kasus ini, Go menyediakan panic, defer, dan recover: mekanisme untuk menangani keadaan luar biasa.
panic langsung menghentikan eksekusi normal. Kata ini dikhususkan untuk error pemrograman, seperti mengakses indeks di luar batas, bukan untuk error yang sudah diperkirakan, seperti input pengguna yang tidak valid:
func MustGetConfig(key string) string {
value, exists := config[key]
if !exists {
panic("missing required config: " + key)
}
return value
}defer menjadwalkan fungsi agar dijalankan saat fungsi di sekitarnya mengembalikan kendali, baik secara normal maupun karena panic. Pemanggilan yang ditunda dijalankan dalam urutan terbalik (terakhir masuk, pertama keluar):
func ProcessFile() {
fmt.Println("Opening file")
defer fmt.Println("Closing file")
fmt.Println("Processing...")
// output: Opening file, Processing..., Closing file
}recover menangkap panic dan mengembalikan eksekusi normal. Ini hanya berfungsi di dalam fungsi yang ditunda:
func SafeOperation() (err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("recovered from panic: %v", r)
}
}()
riskyOperation()
return nil
}Pola ini mengubah panic menjadi error biasa, sehingga programmu dapat terus berjalan. Gunakan pola ini sesekali saja: utamakan mengembalikan error untuk kasus kegagalan yang diperkirakan, dan gunakan panic/recover hanya untuk situasi yang benar-benar luar biasa, seperti state yang rusak atau kondisi yang tidak dapat dipulihkan.
Tantangan
MudahMari buat kalkulator pembagian aman yang menunjukkan cara menggunakan panic, defer, dan recover untuk menangani situasi luar biasa dengan baik. Kalkulatormu akan mencoba operasi berisiko dan mengubah panic menjadi error biasa yang dapat ditangani secara normal.
Kamu akan menyusun kodemu dalam dua file:
calculator.go: Buat logika pembagian dengan pemulihan dari panic.Buat fungsi
Divideyang menerima dua bilangan bulat dan memicu panic dengan pesan"division by zero"jika pembaginya nol. Jika tidak, fungsi ini mengembalikan hasil pembagian berupa bilangan bulat.Buat fungsi
SafeDivideyang menerima dua bilangan bulat dan mengembalikan hasil berupa bilangan bulat serta error. Fungsi ini harus:- Menggunakan
deferdengan fungsi anonim untuk memulihkan diri dari panic apa pun - Jika panic berhasil dipulihkan, ubah panic tersebut menjadi error dengan format
"calculation error: [panic message]" - Memanggil fungsi
Dividedi dalam fungsi ini - Mengembalikan hasil dan
niljika berhasil, atau nol dan error jika panic berhasil dipulihkan
- Menggunakan
main.go: Baca dua bilangan bulat dari input dan gunakanSafeDivideuntuk melakukan perhitungan dengan aman. Tunjukkan juga penggunaandeferdengan mencetak pesan pembersihan dalam urutan yang benar.Fungsi utamamu harus:
- Mencetak
Starting calculationdi awal - Menggunakan
deferuntuk menjadwalkan pencetakanCleanup complete - Menggunakan
deferlain untuk menjadwalkan pencetakanReleasing resources - Memanggil
SafeDividedengan nilai input - Mencetak
Result: [value]atauError: [error message]berdasarkan hasilnya
- Mencetak
Input berikut akan diberikan:
- Baris 1: Bilangan bulat pertama (dividend)
- Baris 2: Bilangan bulat kedua (divisor)
Ingat bahwa pemanggilan yang ditunda dijalankan dalam urutan terbalik (terakhir masuk, pertama keluar), jadi pesan pembersihanmu harus muncul dalam urutan yang berlawanan dengan urutan penundaannya.
Misalnya, jika diberikan 20 dan 4, outputmu harus berupa:
Starting calculation
Result: 5
Releasing resources
Cleanup completeDan jika diberikan 10 dan 0, outputmu harus berupa:
Starting calculation
Error: calculation error: division by zero
Releasing resources
Cleanup completeCoba sendiri
package main
import (
"fmt"
)
func main() {
// Baca input
var dividend, divisor int
fmt.Scanln(÷nd)
fmt.Scanln(&divisor)
// Cetak pesan awal
fmt.Println("Starting calculation")
// TODO: Gunakan defer untuk menjadwalkan pesan "Cleanup complete"
// TODO: Gunakan defer untuk menjadwalkan pesan "Releasing resources"
// Ingat: pemanggilan yang ditunda dijalankan dalam urutan LIFO (terakhir masuk, pertama keluar)
// TODO: Panggil SafeDivide dengan nilai input
// TODO: Cetak "Result: [value]" atau "Error: [error message]"
// berdasarkan apakah error dikembalikan
}
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Pemrograman Berorientasi Objek
1Dasar-Dasar OOP di Go
File EksternalWorkspace Go dan modulePaket dan ImporNama yang Diekspor dan Tidak DieksporPengantar OOP di Gostruct sebagai classMendefinisikan method pada structPointer receiver vs value receiverInisialisasi structFungsi KonstruktorUlasan: Kalkulator Sederhana4Interface
Pengenalan InterfaceImplementasi ImplisitInterface sebagai KontrakInterface Kosong (any)Type AssertionType SwitchKomposisi InterfaceInterface Stringer & ErrorUlasan: Kalkulator Bentuk7Enkapsulasi
Field yang Diekspor vs Tidak DieksporEnkapsulasi Tingkat PackageMethod Getter dan SetterPenyembunyian Informasi di GoRingkasan: Data Siswa10Generics (Go 1.18+)
Pengantar GenericsParameter TipeBatasan TipeStruct GenerikCara Alternatif untuk Method GenerikRingkasan Koleksi Generik2Mendalami Tipe dan Struct
Tipe Dasar dan KompositDefinisi Tipe KustomTag StructStruct AnonimStruct BersarangNilai Nol dan Nilai BawaanRangkuman: Buku Kontak5Komposisi daripada Pewarisan
Mengapa Go Tidak Memiliki PewarisanDasar Penyematan StructPromosi methodMenyematkan Beberapa StructPenyematan vs AgregasiMembayangi method yang DisematkanRangkuman: Hierarki Karyawan8Penanganan Error & OOP
Interface errorTipe Error KustomPembungkusan Error (fmt.Errorf)Error Sentinelerrors.Is() dan errors.As()Panic, Defer, dan RecoverRangkuman: Parser File3Pointer dan Memori
Dasar-Dasar Pointer di GoPointer ke StructPass by Value vs ReferenceFungsi new()Garbage Collection di GoRekap: Pembuat Linked List6Polimorfisme di Go
Polimorfisme melalui InterfaceDuck Typing di GoAturan Pemenuhan InterfaceKoleksi PolimorfikInjeksi DependensiRangkuman: Pemroses Pembayaran9Konkruensi & OOP
Dasar-dasar GoroutineChannel & KomunikasiChannel Ber-buffer vs Tanpa BufferPernyataan selectsync.Mutex & sync.RWMutexsync.WaitGroupDesain Struct yang Aman untuk ThreadRingkasan: Worker PoolLatihan sendiri: Compiler Go online