Objek Galat Terstruktur
Gunakan tabel sebagai objek galat untuk menyampaikan tipe dan konteks.
Objek Galat Terstruktur adalah pelajaran Lua Academy gratis di CoddyKit. Ini adalah pelajaran 4 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Lua Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Lua Academy mencakup 4 pelajaran total.
Mengapa Error Terstruktur?
Error berupa string biasa sulit ditangani secara terprogram. Objek error terstruktur (tabel) membawa informasi jenis dan data konteks, serta dapat diperiksa dan ditindaklanjuti oleh pemanggil. Ini memungkinkan pengalihan berdasarkan error tanpa mengurai string.
-- Plain string: hard to handle programmatically
error("database error: connection refused")
-- Structured: type + data
error({
type = "DatabaseError",
code = "CONN_REFUSED",
host = "localhost",
port = 5432,
message = "connection refused"
})Pola Konstruktor Error
Buat fungsi pabrik error untuk setiap jenis error. Pabrik tersebut membangun tabel dengan bidang yang konsisten: jenis, pesan, dan konteks yang relevan. Metamethod __tostring membuat error tercetak dengan baik.
local ErrorMT = {__tostring = function(e)
return string.format("[%s] %s", e.type, e.message)
end}
local function makeError(errType, msg, data)
local e = {type=errType, message=msg}
if data then for k,v in pairs(data) do e[k]=v end end
return setmetatable(e, ErrorMT)
end
local E = {
notFound = function(name) return makeError("NOT_FOUND","not found: "..name,{name=name}) end,
badInput = function(msg,field) return makeError("BAD_INPUT",msg,{field=field}) end,
}
local ok, err = pcall(error, E.notFound("user:42"))
print(tostring(err)) -- [NOT_FOUND] not found: user:42Pemeriksaan Jenis Objek Error
Setelah menangkap error, periksa apakah nilainya berupa tabel dengan bidang jenis yang dikenal. Dengan demikian, Anda dapat mengalihkan strategi pemulihan yang berbeda berdasarkan jenis error tanpa bergantung pada pencocokan pola string.
local function handleRequest(fn)
local ok, err = pcall(fn)
if ok then return true end
if type(err) == "table" then
if err.type == "NOT_FOUND" then
print("404: " .. err.message)
elseif err.type == "BAD_INPUT" then
print("400: " .. err.message .. " (field: " .. (err.field or "?") .. ")")
else
print("500: unhandled error: " .. tostring(err))
end
else
print("500: " .. tostring(err))
end
return false
endHierarki Error
Simulasikan hierarki error dengan memeriksa bidang is_a atau menggunakan metatabel. Jenis error turunan mewarisi bidang jenis induknya dan dapat diperlakukan sebagai induknya oleh kode yang tidak memerlukan perincian khusus.
local function isError(e, errType)
if type(e) ~= "table" then return false end
return e.type == errType or e.parentType == errType
end
local function makeDbError(code, msg)
return {type="DbError:"..code, parentType="DbError", code=code, message=msg}
end
local err = makeDbError("TIMEOUT","query timed out")
print(isError(err, "DbError")) -- true
print(isError(err, "DbError:TIMEOUT")) -- true
print(isError(err, "NetworkError")) -- falseMembungkus Error
Saat menangkap dan melempar ulang error, bungkus error asli untuk menambahkan konteks tanpa kehilangannya. Pembungkus tersebut memiliki jenisnya sendiri dan membawa error asli sebagai penyebab.
local function wrapError(msg, cause)
return {
type = "WrappedError",
message = msg,
cause = cause,
}
end
local function loadConfig(path)
local ok, err = pcall(function()
local f = assert(io.open(path,"r"))
local content = f:read("a")
f:close()
return content
end)
if not ok then
error(wrapError("failed to load config: "..path, err))
end
end
local ok2, e = pcall(loadConfig, "missing.cfg")
if not ok2 then
print(e.message)
print("Caused by:", tostring(e.cause))
endKode Error vs Jenis Error
Dua konvensi umum: kode error (numerik, seperti kode status HTTP) dan string jenis error (nama semantik). Kode error mudah dibandingkan secara numerik; string jenis menjelaskan maknanya sendiri. Banyak sistem menggunakan keduanya.
local STATUS = {OK=200, NOT_FOUND=404, SERVER_ERROR=500, BAD_REQUEST=400}
local function makeStatusError(status, msg)
return {status=status, message=msg, type="HTTPError"}
end
local function handleError(e)
if e.status == STATUS.NOT_FOUND then
print("Resource not found:", e.message)
elseif e.status >= 500 then
print("Server error:", e.message)
else
print("Error", e.status, e.message)
end
end
handleError(makeStatusError(404, "user not found"))Stack Error (Rantai Penyebab)
Jika suatu error disebabkan oleh error lain, rangkailah keduanya. Ini memberikan gambaran lengkap tentang hal yang salah pada setiap lapisan aplikasi. Lepaskan pembungkus rantai tersebut untuk mencatat atau menampilkan keseluruhan riwayat error.
local function unwindCause(e, depth)
depth = depth or 0
local pad = string.rep(" ", depth)
if type(e) == "table" then
print(pad .. (e.type or "Error") .. ": " .. (e.message or "?"))
if e.cause then unwindCause(e.cause, depth+1) end
else
print(pad .. tostring(e))
end
end
local inner = {type="IoError", message="permission denied"}
local outer = {type="ConfigError", message="cannot load config", cause=inner}
unwindCause(outer)
-- ConfigError: cannot load config
-- IoError: permission deniedError dalam Konteks Callback
Saat error terjadi di dalam callback (handler peristiwa, iterator), error tersebut merambat ke pemanggil callback. Gunakan pcall untuk menangkapnya dan melaporkannya dengan konteks callback yang gagal.
local function runCallbacks(callbacks, data)
local errors = {}
for name, fn in pairs(callbacks) do
local ok, err = pcall(fn, data)
if not ok then
errors[#errors+1] = {callback=name, error=err}
end
end
return errors
end
local cbs = {
validate = function(d) assert(d.name, "name required") end,
transform = function(d) d.name = d.name:upper() end,
}
local errs = runCallbacks(cbs, {})
for _, e in ipairs(errs) do
print(e.callback, "->", e.error)
endMencetak Detail Error
Buat helper yang mencetak objek error dengan cara terstruktur dan mudah dibaca—menangani error berupa string maupun tabel. Ini berguna di batas aplikasi tempat error dicatat atau ditampilkan kepada pengguna.
local function printError(err, prefix)
prefix = prefix or "Error"
if type(err) ~= "table" then
print(prefix .. ": " .. tostring(err))
return
end
print(prefix .. " [" .. (err.type or "unknown") .. "]")
print(" Message: " .. (err.message or "?"))
for k, v in pairs(err) do
if k ~= "type" and k ~= "message" and k ~= "cause" then
print(" " .. k .. ": " .. tostring(v))
end
end
if err.cause then printError(err.cause, " Caused by") end
endAssertion dengan Error Terstruktur
Buat assertT (assert dengan error bertipe) yang menghasilkan error terstruktur, bukan string biasa. Ini memudahkan pemanggil menguji jenis error tertentu.
local function assertT(cond, errType, msg, data)
if not cond then
local e = {type=errType, message=msg}
if data then for k,v in pairs(data) do e[k]=v end end
error(e, 2)
end
return cond
end
local function createUser(name, age)
assertT(type(name)=="string", "BAD_INPUT", "name must be string", {field="name"})
assertT(age >= 0 and age <= 150, "BAD_INPUT", "invalid age", {field="age", value=age})
return {name=name, age=age}
end
local ok, err = pcall(createUser, "Alice", -5)
if not ok then print(err.type, err.field, err.value) endPemeriksaan Singkat
Apa keunggulan utama meneruskan tabel ke error() alih-alih string?
Rangkuman: Error Terstruktur
Rangkuman:
- Teruskan tabel ke
error()untuk error yang terstruktur dan dapat diperiksa - Sertakan: jenis, pesan, dan bidang konteks yang relevan
- Tambahkan
__tostringuntuk keluaran yang mudah dibaca - Bungkus error untuk menambahkan konteks tanpa kehilangan penyebabnya
- Pengalihan berdasarkan jenis dalam handler: periksa
err.type, bukan pola string
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Objek Galat Terstruktur” gratis?
Ya — teks lengkap “Objek Galat Terstruktur” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Lua Academy, upgrade ke CoddyKit PRO. Kursus Lua Academy mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Objek Galat Terstruktur”?
Gunakan tabel sebagai objek galat untuk menyampaikan tipe dan konteks. Kamu berlatih Lua Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai Lua Academy?
Tidak diperlukan pengalaman sebelumnya. Lua Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 4 dari 4.
Berapa lama pelajaran “Objek Galat Terstruktur” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran Lua Academy ini?
Ya. Setiap pelajaran Lua Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- Fungsi error()
- Pemanggilan Terlindungi dengan pcall
- xpcall dan Penangan Pesan
- Objek Galat Terstruktur