← Danh sách bài học Bài 13/20

⚠️ Bài 13: Xử Lý Lỗi (Error Handling)

⏱️ 20 phút | 📚 Trung bình

🎯 Mục tiêu:

1. Error Trong Go

Go không có exceptions như Java/Python. Thay vào đó, lỗi được trả về như giá trị bình thường.

import (
    "fmt"
    "os"
)

func main() {
    // Mở file - có thể lỗi
    file, err := os.Open("file.txt")
    
    // Kiểm tra lỗi NGAY LẬP TỨC
    if err != nil {
        fmt.Println("Lỗi:", err)
        return
    }
    
    defer file.Close()
    fmt.Println("Mở file thành công!")
}
💡 Pattern chuẩn: Luôn kiểm tra if err != nil ngay sau khi gọi hàm có thể lỗi.

2. Trả Về Error Từ Hàm

import (
    "errors"
    "fmt"
)

func divide(a, b int) (int, error) {
    if b == 0 {
        return 0, errors.New("không thể chia cho 0")
    }
    return a / b, nil
}

func main() {
    result, err := divide(10, 0)
    if err != nil {
        fmt.Println("Lỗi:", err)
        return
    }
    fmt.Println("Kết quả:", result)
}

3. fmt.Errorf - Lỗi Có Format

import "fmt"

func greet(name string) error {
    if name == "" {
        return fmt.Errorf("tên không được để trống")
    }
    if len(name) < 2 {
        return fmt.Errorf("tên '%s' quá ngắn (tối thiểu 2 ký tự)", name)
    }
    fmt.Println("Xin chào", name)
    return nil
}

4. Custom Error Type

// Custom error struct
type ValidationError struct {
    Field   string
    Message string
}

// Implement error interface
func (e ValidationError) Error() string {
    return fmt.Sprintf("%s: %s", e.Field, e.Message)
}

func validateAge(age int) error {
    if age < 0 {
        return ValidationError{
            Field:   "age",
            Message: "tuổi không thể âm",
        }
    }
    return nil
}

5. Panic và Recover

// panic - dừng chương trình ngay lập tức
func mustDivide(a, b int) int {
    if b == 0 {
        panic("chia cho 0!")
    }
    return a / b
}

// recover - bắt panic
func safeCall() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered:", r)
        }
    }()
    
    mustDivide(10, 0)  // Sẽ panic
    fmt.Println("Sau panic")  // Không chạy
}
⚠️ Lưu ý: Chỉ dùng panic cho lỗi KHÔNG THỂ PHỤC HỒI. Bình thường nên dùng error return.

📝 Tóm Tắt