Custom Errors di Go
Selain errors.New dan fmt.Errorf, kamu bisa membuat tipe error sendiri untuk menyimpan informasi lebih detail.
Custom Error Type
type ValidationError struct {
Field string
Message string
}
func (e *ValidationError) Error() string {
return fmt.Sprintf("validasi gagal pada %s: %s", e.Field, e.Message)
}
func validasiUmur(umur int) error {
if umur < 0 {
return &ValidationError{
Field: "umur",
Message: "tidak boleh negatif",
}
}
if umur > 150 {
return &ValidationError{
Field: "umur",
Message: "tidak realistis",
}
}
return nil
}
Error Wrapping (Go 1.13+)
import (
"errors"
"fmt"
)
// Wrap error dengan context
func bacaConfig() error {
err := bukaFile("config.json")
if err != nil {
return fmt.Errorf("gagal baca config: %w", err)
}
return nil
}
// Unwrap dan cek error asli
err := bacaConfig()
if errors.Is(err, os.ErrNotExist) {
fmt.Println("File tidak ditemukan")
}
// Type assertion untuk custom error
var valErr *ValidationError
if errors.As(err, &valErr) {
fmt.Println("Field:", valErr.Field)
}
Sentinel Errors
Error yang didefinisikan sebagai variabel package-level untuk perbandingan:
var (
ErrNotFound = errors.New("tidak ditemukan")
ErrUnauthorized = errors.New("tidak memiliki akses")
)
func cariItem(id int) (string, error) {
if id <= 0 {
return "", ErrNotFound
}
return "Item", nil
}
_, err := cariItem(-1)
if errors.Is(err, ErrNotFound) {
fmt.Println("Item tidak ada")
}
Best Practices
- Gunakan
errors.Newuntuk error sederhana - Gunakan
fmt.Errorf("context: %w", err)untuk wrap error dengan context - Buat custom error type jika perlu menyimpan data tambahan
- Gunakan
errors.Isdanerrors.Asuntuk membandingkan error - Prefix error message dengan nama fungsi/package untuk traceability