Error Handling
Error handling di Go menggunakan tipe error sebagai nilai return, bukan exception seperti bahasa lain. Ini membuat penanganan error lebih eksplisit dan terkontrol.
Contoh Masalah
Bagaimana cara:
- Menangani error dengan benar
- Membuat custom error
- Mengelola error di berbagai situasi
Penyelesaian
package main
import (
"errors"
"fmt"
"math"
"os"
"strconv"
)
// 1. Custom error type
type DivisionError struct {
dividend float64
divisor float64
message string
}
func (e *DivisionError) Error() string {
return fmt.Sprintf("%s: %f / %f", e.message, e.dividend, e.divisor)
}
// 2. Function yang mengembalikan error
func divide(x, y float64) (float64, error) {
if y == 0 {
return 0, &DivisionError{
dividend: x,
divisor: y,
message: "tidak bisa membagi dengan nol",
}
}
return x / y, nil
}
// 3. Function dengan multiple error cases
func sqrt(x float64) (float64, error) {
if x < 0 {
return 0, errors.New("tidak bisa menghitung akar dari angka negatif")
}
return math.Sqrt(x), nil
}
// 4. Wrapping errors
type ValidationError struct {
Field string
Err error
}
func (e *ValidationError) Error() string {
return fmt.Sprintf("validasi gagal pada field %s: %v", e.Field, e.Err)
}
func (e *ValidationError) Unwrap() error {
return e.Err
}
// 5. Function yang menggunakan wrapped error
func validateAge(age string) error {
n, err := strconv.Atoi(age)
if err != nil {
return &ValidationError{
Field: "age",
Err: err,
}
}
if n < 0 || n > 150 {
return &ValidationError{
Field: "age",
Err: errors.New("umur harus antara 0 dan 150"),
}
}
return nil
}
func main() {
// Contoh 1: Basic error handling
result, err := divide(10, 0)
if err != nil {
fmt.Printf("Error: %v\n", err)
} else {
fmt.Printf("Hasil: %f\n", result)
}
// Contoh 2: Multiple error cases
numbers := []float64{16, -4, 25, 0}
fmt.Printf("\nMenghitung akar:\n")
for _, num := range numbers {
result, err := sqrt(num)
if err != nil {
fmt.Printf("Error untuk %f: %v\n", num, err)
continue
}
fmt.Printf("Akar dari %f adalah %f\n", num, result)
}
// Contoh 3: File operations dengan error handling
fmt.Printf("\nMencoba membaca file:\n")
content, err := os.ReadFile("nonexistent.txt")
if err != nil {
if os.IsNotExist(err) {
fmt.Println("File tidak ditemukan")
} else {
fmt.Printf("Error lain: %v\n", err)
}
} else {
fmt.Printf("Konten file: %s\n", content)
}
// Contoh 4: Validation errors
fmt.Printf("\nValidasi umur:\n")
ages := []string{"25", "-5", "200", "abc"}
for _, age := range ages {
err := validateAge(age)
if err != nil {
var validErr *ValidationError
if errors.As(err, &validErr) {
fmt.Printf("Validation error: %v\n", validErr)
} else {
fmt.Printf("Unexpected error: %v\n", err)
}
continue
}
fmt.Printf("Umur %s valid\n", age)
}
// Contoh 5: Error wrapping dan unwrapping
fmt.Printf("\nError wrapping:\n")
err = validateAge("abc")
if err != nil {
fmt.Printf("Original error: %v\n", err)
if wrapped := errors.Unwrap(err); wrapped != nil {
fmt.Printf("Wrapped error: %v\n", wrapped)
}
}
}
Penjelasan Kode
Basic Error Handling
- Return error sebagai nilai kedua
- Cek error dengan if
- Nil berarti tidak ada error
Custom Error
- Implement interface Error()
- Bisa tambah informasi tambahan
- Lebih deskriptif
Error Wrapping
- Menambah konteks ke error
- Bisa di-unwrap
- Chain of responsibility
Output
Error: tidak bisa membagi dengan nol: 10.000000 / 0.000000
Menghitung akar:
Akar dari 16.000000 adalah 4.000000
Error untuk -4.000000: tidak bisa menghitung akar dari angka negatif
Akar dari 25.000000 adalah 5.000000
Akar dari 0.000000 adalah 0.000000
Mencoba membaca file:
File tidak ditemukan
Validasi umur:
Umur 25 valid
Validation error: validasi gagal pada field age: umur harus antara 0 dan 150
Validation error: validasi gagal pada field age: umur harus antara 0 dan 150
Validation error: validasi gagal pada field age: strconv.Atoi: parsing "abc": invalid syntax
Error wrapping:
Original error: validasi gagal pada field age: strconv.Atoi: parsing "abc": invalid syntax
Wrapped error: strconv.Atoi: parsing "abc": invalid syntax
Tips
- Selalu periksa error yang dikembalikan
- Buat custom error yang informatif
- Gunakan error wrapping untuk konteks
- Jangan ignore error
- Log error dengan informasi yang cukup