مدیریت خطاها در لوا

error، assert، pcall و xpcall برای مدیریت امن خطاها در لوا

خطا در لوا

وقتی چیزی اشتباه پیش برود، لوا خطا (error) می‌دهد و برنامه متوقف می‌شود — مگر اینکه خطا را مدیریت کنید!

error — ایجاد خطا

local function divide(a, b)
  if b == 0 then
    error("تقسیم بر صفر مجاز نیست!", 2)
  end
  return a / b
end

print(divide(10, 2))   -- 5
-- print(divide(10, 0))   -- برنامه متوقف می‌شود!
عدد ۲ در error(msg, 2) یعنی خطا به فراخواننده نسبت داده شود (خط گزارش‌شده درست‌تر باشد).

assert — بررسی و خطا در یک خط

local function sqrt(x)
  assert(x >= 0, "عدد منفی جذر ندارد!")
  return math.sqrt(x)
end

print(sqrt(16))   -- 4
-- sqrt(-1)      -- خطا: عدد منفی جذر ندارد!

pcall — اجرای امن

pcall (protected call) تابع را در «محافظ» اجرا می‌کند — اگر خطا رخ دهد، برنامه متوقف نمی‌شود:

local ok, result = pcall(divide, 10, 0)

if ok then
  print("نتیجه:", result)
else
  print("خطا گرفتیم:", result)
end
-- خطا گرفتیم: تقسیم بر صفر مجاز نیست!

pcall با توابع بی‌نام

local ok, err = pcall(function()
  error("مشکلی پیش آمد!")
end)

print(ok)   -- false
print(err)  -- مشکلی پیش آمد!

الگوی کامل: تابع امن

local function safeDivide(a, b)
  if b == 0 then
    return nil, "تقسیم بر صفر!"
  end
  return a / b
end

local result, err = safeDivide(10, 0)
if result then
  print("نتیجه:", result)
else
  print("خطا:", err)
end

xpcall — با مدیریت خطا

xpcall مثل pcall است اما یک تابع handler هم می‌گیرد:

local function handler(err)
  return "خطای مدیریت‌شده: " .. tostring(err)
end

local ok, result = xpcall(function()
  error("بوم!")
end, handler)

print(result)   -- خطای مدیریت‌شده: بوم!

خطاها می‌توانند جدول باشند!

local function validate(age)
  if type(age) ~= "number" then
    error({code = 400, message = "سن باید عدد باشد!"})
  end
  return age >= 18
end

local ok, err = pcall(validate, "بیست")
if not ok then
  print("کد خطا:", err.code)
  print("پیام:", err.message)
end

جدول خلاصه

ابزارکار
error(msg)ایجاد خطا
assert(cond, msg)اگر شرط غلط بود، خطا
pcall(f, ...)اجرای امن — برمی‌گرداند ok, result
xpcall(f, handler)اجرای امن با handler خطا
در لوا برخلاف پایتون/روبی try/catch نداریم — الگوی رایج: return nil, err برای خطاهای قابل پیش‌بینی و pcall برای خطاهای غیرمنتظره.

این مبحث بخشی از دوره آموزش کامل لوا است.

ابزارهای مرتبط