مدیریت خطاها (Errors)
مدیریت خطا در Go: error، errors.New، fmt.Errorf و الگوهای رایج.
فلسفه خطا در Go
Go برخلاف Java/Python از exception استفاده نمیکند! به جای try/catch، خطاها مقدار بازگشتی هستند:
result, err := doSomething()
if err != nil {
// خطا رخ داد
}
نوع error
error یک اینترفیس داخلی است:
type error interface {
Error() string
}
ساخت خطا
با errors.New
import "errors"
err := errors.New("خطای ساده")
با fmt.Errorf — با قالببندی
err := fmt.Errorf("عدد %d خارج از محدوده است", 42)
با %w — پیچیدن خطا (Wrapping)
if err := readConfig(); err != nil {
return fmt.Errorf("خواندن تنظیمات: %w", err) ← خطای اصلی حفظ میشود
}
الگوی استاندارد
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, fmt.Errorf("تقسیم بر صفر")
}
return a / b, nil ← nil یعنی بدون خطا
}
بررسی خطا
result, err := divide(10, 0)
if err != nil {
fmt.Println("خطا:", err)
return ← معمولاً return یا os.Exit
}
fmt.Println("نتیجه:", result)
بررسی خطای خاص با errors.Is
var ErrNotFound = errors.New("پیدا نشد")
func find(id int) error {
return ErrNotFound
}
err := find(42)
if errors.Is(err, ErrNotFound) {
fmt.Println("رکورد وجود ندارد")
}
خطای سفارشی (Custom Error)
type AppError struct {
Code int
Message string
}
func (e *AppError) Error() string {
return fmt.Sprintf("[%d] %s", e.Code, e.Message)
}
return &AppError{Code: 404, Message: "یافت نشد"}
هرگز خطا را
_ نکنید مگر مطمئن باشید — خطاهای نادیدهگرفتهشده منبع باگهای سختیاب هستند!چرا این روش بهتر است؟
- صریح: در امضای تابع معلوم است خطا دارد یا نه
- کنترلشده: جریان عادی از خطا جدا است
- بدون stack پنهان: همه چیز واضح است
این مبحث بخشی از دوره آموزش کامل گو است.