Di Go, error adalah nilai — dan bagaimana Anda memperlakukannya menentukan seberapa mudah sistem di-debug saat jam 3 pagi. Ini pola error handling yang saya pakai di API production supaya jejaknya kaya untuk developer, tapi pesannya aman untuk pengguna.
Wrapping menjaga konteks tanpa kehilangan asal
Mengembalikan error mentah ke atas menghilangkan konteks; menelannya dan membuat error baru menghilangkan asal. Jalan tengahnya adalah membungkus dengan %w — menambahkan konteks di setiap lapisan sambil mempertahankan rantai aslinya.
Dengan errors.Is dan errors.As, lapisan atas tetap bisa memeriksa jenis error di dasar rantai, meski sudah dibungkus beberapa kali. Konteks bertambah, identitas tidak hilang.
Sentinel error untuk keputusan, bukan string matching
Membandingkan error dengan mencocokkan teks pesannya adalah kode rapuh yang patah begitu pesannya diubah. Sentinel error (variabel error yang dideklarasikan) memberi identitas stabil untuk kondisi yang perlu dibedakan — mis. 'tidak ditemukan' vs 'sudah ada'.
Ini yang memungkinkan lapisan HTTP memutuskan 404 vs 409 tanpa menebak dari teks — keputusan berbasis tipe, bukan string.
Petakan ke HTTP di satu choke point
Menyebar kode status HTTP ke seluruh handler membuat perilaku error tidak konsisten. Lebih baik satu titik yang menerjemahkan error domain ke respons HTTP: sentinel tertentu jadi 4xx dengan pesan aman dan bisa di-i18n, sisanya jadi 5xx dengan detail hanya di log.
Pengguna mendapat pesan yang jelas dan tidak membocorkan struktur internal; developer mendapat jejak lengkap di log. Keduanya menang tanpa saling mengorbankan.
Ringkasan
Error handling Go yang baik: bungkus dengan %w untuk konteks, pakai sentinel untuk keputusan berbasis tipe, dan petakan ke HTTP di satu tempat dengan pesan aman untuk pengguna serta jejak kaya untuk log.