Error Handling
Error sebagai nilai: errors.New, fmt.Errorf, pembungkusan, dan custom error.
error adalah interface biasa
type error interface {
Error() string
}
Function yang bisa gagal mengembalikan error sebagai nilai terakhir. Jika tidak ada masalah, nilainya nil.
func bagi(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("tidak bisa dibagi nol")
}
return a / b, nil
}
Pola "if err != nil"
hasil, err := bagi(10, 0)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("Hasil:", hasil)
Terkesan repetitif, tetapi membuat alur kegagalan eksplisit — kamu selalu tahu di mana error bisa terjadi.
Membuat error
errors.New("pesan")— pesan tetap.fmt.Errorf("stok %s kurang: %d", nama, n)— pesan berformat.
Membungkus error dengan %w
Tambahkan konteks tanpa kehilangan error aslinya:
if err != nil {
return fmt.Errorf("baca config: %w", err)
}
Lalu periksa penyebabnya dengan errors.Is:
if errors.Is(err, os.ErrNotExist) { ... }
Sentinel error
Error bernilai tetap yang bisa dibandingkan:
var ErrTidakDitemukan = errors.New("tidak ditemukan")
Custom error
Buat tipe sendiri yang memiliki method Error() agar bisa membawa data tambahan:
type ErrStok struct {
Nama string
Sisa int
}
func (e ErrStok) Error() string {
return fmt.Sprintf("stok %s tinggal %d", e.Nama, e.Sisa)
}
// memeriksa:
var es ErrStok
if errors.As(err, &es) { fmt.Println(es.Sisa) }
Aturan emas
- Jangan abaikan error (
_) kecuali kamu paham alasannya. - Tangani error sekali: kembalikan ke atas atau catat, jangan keduanya.
- Tambahkan konteks saat meneruskan error ke atas.
- Gunakan
panichanya untuk bug yang tidak mungkin terjadi.