0Pricing
Lua Academy · บทเรียน

ฟังก์ชัน error()

สร้างข้อผิดพลาดด้วย error() และทำความเข้าใจระดับกับข้อความของข้อผิดพลาด

ฟังก์ชัน error() เป็นบทเรียน Lua Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Lua Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Lua Academy มีบทเรียนทั้งหมด 4 บทเรียน

การยกข้อผิดพลาด

error(message, level) ยกข้อผิดพลาดของ Lua การทำงานจะหยุดลง และข้อผิดพลาดจะถูกส่งย้อนขึ้นไปตามลำดับการเรียกฟังก์ชันจนกว่าจะถูกจับด้วย pcall หรือ xpcall หรือจนกว่าโปรแกรมจะจบการทำงาน ข้อความสามารถเป็นค่าใดก็ได้ เช่น สตริง ตาราง หรือตัวเลข

local function divide(a, b)
  if b == 0 then
    error("division by zero")
  end
  return a / b
end

print(divide(10, 2))    -- 5.0
-- divide(10, 0)        -- ERROR: division by zero

ระดับข้อผิดพลาด

อาร์กิวเมนต์ตัวที่สองของ error() กำหนดตำแหน่งที่รายงานข้อผิดพลาด ระดับ 1 (ค่าเริ่มต้น) ชี้ไปยังจุดเรียก error() เอง ระดับ 2 ชี้ไปยังผู้เรียก ระดับ 0 จะไม่เพิ่มข้อมูลตำแหน่ง ใช้ระดับ 2 ในฟังก์ชันของไลบรารีเพื่อชี้ให้เห็นโค้ดของผู้ใช้

local function assertPositive(n, name)
  if n <= 0 then
    error((name or "value") .. " must be positive, got " .. n, 2)
    -- level 2: blame the caller, not this function
  end
  return n
end

local function compute(x)
  assertPositive(x, "x")   -- error points here if x <= 0
  return math.sqrt(x)
end

compute(-5)  -- error: "x must be positive, got -5" at compute() call

ข้อผิดพลาดที่มีออบเจ็กต์ตาราง

การส่งตารางเป็นค่าข้อผิดพลาดทำให้ผู้เรียกตรวจสอบข้อมูลข้อผิดพลาดที่มีโครงสร้างได้ เช่น รหัสข้อผิดพลาด ข้อความ และบริบท วิธีนี้ให้ข้อมูลมากกว่าสตริงธรรมดาและเปิดทางให้จัดการข้อผิดพลาดด้วยโปรแกรม

local function openDB(host, port)
  if port < 1 or port > 65535 then
    error({code="INVALID_PORT", port=port,
           msg="port out of range: " .. port})
  end
  -- ... connect
  return {host=host, port=port}
end

local ok, err = pcall(openDB, "localhost", -1)
if not ok and type(err) == "table" then
  print("Code:", err.code)    -- INVALID_PORT
  print("Port:", err.port)    -- -1
  print("Msg:", err.msg)
end

assert() ในรูปแบบย่อ

assert(v, msg) มีความหมายเทียบเท่ากับ if not v then error(msg, 2) end; return v, ... เหมาะสำหรับตรวจสอบเงื่อนไขเบื้องต้น หาก v เป็นค่าที่ถือว่าเป็นจริง assert จะคืนค่าอาร์กิวเมนต์ทั้งหมด (มีประโยชน์สำหรับการเรียกต่อเนื่อง)

local function sqrt(n)
  assert(type(n) == "number", "expected number, got " .. type(n))
  assert(n >= 0, "sqrt of negative: " .. n)
  return math.sqrt(n)
end

print(sqrt(16))    -- 4.0
print(sqrt(2))     -- 1.4142...
-- sqrt("hi")      -- ERROR: expected number, got string

error() กับ return nil,err

มีแบบแผนสองรูปแบบสำหรับสื่อว่าการทำงานล้มเหลว: error() (รูปแบบข้อยกเว้น) หรือ return nil, msg (รูปแบบฟังก์ชัน) ใช้ error() สำหรับเงื่อนไขที่ไม่คาดคิดอย่างแท้จริง (ข้อผิดพลาดในการเขียนโปรแกรมหรือการละเมิดข้อตกลง) ใช้ nil, msg สำหรับความล้มเหลวที่คาดการณ์ได้ (ไม่พบไฟล์หรือหมดเวลาการเชื่อมต่อเครือข่าย)

-- Exception style (programming error)
local function mustExist(t, key)
  local v = t[key]
  if v == nil then error("required key missing: " .. key, 2) end
  return v
end

-- Functional style (expected failure)
local function findUser(id)
  -- ... database query
  return nil, "user not found"  -- expected: user may not exist
end

ข้อผิดพลาดในเมธาเมธอด

สามารถยกข้อผิดพลาดภายในเมธาเมธอดได้ หากเมธาเมธอดเกิดข้อผิดพลาด ข้อผิดพลาดนั้นจะถูกส่งต่อไปยังโค้ดที่เรียกใช้การดำเนินการดังกล่าว (เช่น นิพจน์เลขคณิต) โปรดตรวจสอบอินพุตที่ไม่ถูกต้องในเมธาเมธอดเสมอ

local SafeDiv = {}
SafeDiv.__index = SafeDiv

SafeDiv.__div = function(a, b)
  if b.value == 0 then
    error("SafeDiv: division by zero", 2)
  end
  return SafeDiv.new(a.value / b.value)
end

function SafeDiv.new(v)
  return setmetatable({value=v}, SafeDiv)
end

local a = SafeDiv.new(10)
local b = SafeDiv.new(0)
local ok, err = pcall(function() return a / b end)
print(ok, err)

ประเภทข้อผิดพลาดแบบกำหนดเอง

สร้างตัวช่วยสำหรับสร้างออบเจ็กต์ข้อผิดพลาดที่มีชนิดกำกับไว้ โดยให้มีป้ายระบุชนิดเพื่อให้ผู้เรียกแยกแยะข้อผิดพลาดแต่ละประเภทและจัดการได้อย่างเหมาะสม

local function newError(kind, msg, extra)
  return setmetatable(
    {kind=kind, message=msg, extra=extra},
    {__tostring = function(e)
      return "[" .. e.kind .. "] " .. e.message
    end}
  )
end

local E = {
  notFound = function(name) return newError("NOT_FOUND","not found: "..name) end,
  badInput = function(msg)  return newError("BAD_INPUT", msg) end,
}

local ok, err = pcall(error, E.notFound("config.json"))
if not ok then print(err.kind, err.message) end

การส่งต่อข้อผิดพลาด

เมื่อฟังก์ชันหนึ่งเรียกใช้ฟังก์ชันอื่นแล้วเกิดข้อผิดพลาด ข้อผิดพลาดนั้นจะถูกส่งต่อขึ้นไปตามลำดับการเรียกโดยอัตโนมัติ คุณไม่จำเป็นต้องโยนข้อผิดพลาดซ้ำ เพียงอย่าดักจับไว้ ควรดักจับข้อผิดพลาดเฉพาะในระดับที่สามารถจัดการหรือรายงานได้อย่างมีความหมาย

local function step3() error("step3 failed") end
local function step2() step3() end
local function step1() step2() end

local ok, err = pcall(step1)
if not ok then
  -- err includes the source location
  print("Caught at top level:", err)
end
-- Error: input:1: step3 failed

ร่องรอยการเรียกด้วย debug.traceback

error() แบบธรรมดาจะให้บริบทเพียงหนึ่งบรรทัด หากต้องการร่องรอยการเรียกทั้งหมด ให้ใช้ debug.traceback(msg) เป็นค่าข้อผิดพลาด โดยทั่วไปจะทำเช่นนี้ในตัวจัดการของ xpcall

local function buggy()
  local t = nil
  return t.field   -- nil indexing: error
end

local ok, err = xpcall(buggy, function(e)
  return debug.traceback(e, 2)  -- full stack trace
end)

if not ok then
  print(err)  -- full traceback
end

การโยนข้อผิดพลาดซ้ำ

บางครั้งคุณดักจับข้อผิดพลาดเพื่อเพิ่มบริบท แล้วจึงโยนข้อผิดพลาดนั้นซ้ำ ให้ใช้ error(err, 0) (ระดับ 0) เมื่อต้องการโยนข้อผิดพลาดชนิดสตริงซ้ำ เพื่อไม่ให้มีคำนำหน้าตำแหน่งเพิ่มในข้อความที่จัดรูปแบบไว้แล้ว

local function loadAndParse(path)
  local ok, err = pcall(function()
    local f = io.open(path, "r")
    if not f then error("cannot open: " .. path) end
    local content = f:read("a")
    f:close()
    return content
  end)
  if not ok then
    error("loadAndParse failed: " .. err, 0)  -- re-raise with context
  end
end

local ok2, msg = pcall(loadAndParse, "missing.txt")
print(ok2, msg)

ตรวจสอบอย่างรวดเร็ว

ระดับ 2 ใน error("msg", 2) หมายถึงอะไร

ทบทวน: error()

สรุป:

  • error(msg, level) — ยกข้อผิดพลาดขึ้นมา โดยระดับ 2 จะระบุว่าผู้เรียกเป็นต้นเหตุ
  • ใช้ตารางสำหรับข้อผิดพลาดแบบมีโครงสร้าง ซึ่งประกอบด้วยชนิดและบริบท
  • assert(v, msg) — การตรวจสอบเงื่อนไขเบื้องต้นตามรูปแบบที่นิยมใช้
  • ใช้ error() สำหรับข้อผิดพลาดในโปรแกรม ส่วนความล้มเหลวที่คาดหมายได้ให้คืนค่า nil+err
  • โยนซ้ำด้วย error(err, 0) เพื่อคงรูปแบบข้อความเดิม

คำถามที่พบบ่อย

บทเรียน “ฟังก์ชัน error()” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “ฟังก์ชัน error()” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Lua Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Lua Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “ฟังก์ชัน error()”

สร้างข้อผิดพลาดด้วย error() และทำความเข้าใจระดับกับข้อความของข้อผิดพลาด คุณปฏิบัติ Lua Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Lua Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Lua Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน

บทเรียน “ฟังก์ชัน error()” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Lua Academy นี้ได้ไหม

ได้ บทเรียน Lua Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. ฟังก์ชัน error()
  2. การเรียกใช้แบบป้องกันด้วย pcall
  3. xpcall และตัวจัดการข้อความ
  4. ออบเจกต์ข้อผิดพลาดแบบมีโครงสร้าง
← กลับไปที่ Lua Academy