Strukturerte feilobjekter
Send tabeller som feilobjekter for å formidle type og kontekst.
Strukturerte feilobjekter er en gratis leksjon i Lua Academy på CoddyKit. Dette er leksjon 4 av 4. Du kan lese valgfritt 3 leksjoner fra denne læringsstien gratis i sin helhet – deretter låser CoddyKit PRO opp alle leksjoner, samt praktisk øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Lua Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Lua Academy inneholder totalt 4 leksjoner.
Hvorfor strukturerte feil?
Vanlige strengfeil er vanskelige å håndtere programmatisk. Strukturerte feilobjekter (tabeller) inneholder typeinformasjon og kontekstdata, og kallere kan undersøke og reagere på dem. Dette muliggjør feilbasert ruting uten strengparsing.
-- 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"
})Mønster for feilkonstuktører
Opprett en feilfabrikkfunksjon for hver feiltype. Fabrikken bygger en tabell med konsistente felt: type, melding og relevant kontekst. En __tostring-metamethod gjør at feilen skrives ut på en lesbar måte.
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:42Typesjekking av feilobjekter
Etter at De har fanget en feil, bør De kontrollere om den er en tabell med et kjent typefelt. Da kan De velge ulike strategier for gjenoppretting basert på feiltypen, uten å være avhengig av mønstergjenkjenning for strenger.
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
endFeilhierarki
Simuler et feilhierarki ved å kontrollere is_a-felter eller bruke metatables. Underordnede feiltyper arver feltene til den overordnede feiltypen og kan behandles som den overordnede typen av kode som ikke trenger detaljene.
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")) -- falsePakke inn feil
Når De fanger og kaster en feil på nytt, bør De pakke inn den opprinnelige feilen for å legge til kontekst uten å miste den. Omslaget har sin egen type og inneholder den opprinnelige feilen som årsak.
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))
endFeilkoder kontra feiltyper
To vanlige konvensjoner er feilkoder (numeriske, som HTTP-statuskoder) og feiltypestrenger (semantiske navn). Feilkoder er enkle å sammenligne numerisk, mens typestrenger forklarer seg selv. Mange systemer bruker begge deler.
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"))Feilstakk (årsakskjede)
Når en feil skyldes en annen feil, bør De lenke dem sammen. Dette gir et fullstendig bilde av hva som gikk galt på hvert lag i applikasjonen. Pakk ut kjeden for å logge eller vise hele feilhistorien.
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 deniedFeil i callback-kontekst
Når feil oppstår inne i callbacks (hendelsesbehandlere, iteratorer), propageres de til den som kalte callbacken. Bruk pcall til å fange dem og rapportere hvilken callback som mislyktes, sammen med relevant kontekst.
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)
endSkrive ut feildetaljer
En hjelpefunksjon som skriver ut et feilobjekt på en strukturert og lesbar måte, og som håndterer både streng- og tabellfeil. Dette er nyttig ved applikasjonsgrenser der feil logges eller vises til brukere.
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
endAssert med strukturerte feil
Opprett en assertT (assert med typede feil) som utløser en strukturert feil i stedet for en vanlig streng. Da blir det enkelt for kallere å teste etter bestemte feiltyper.
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) endHurtigsjekk
Hva er den viktigste fordelen ved å sende en tabell til error() i stedet for en streng?
Oppsummering: strukturerte feil
Oppsummering:
- Send tabeller til
error()for strukturerte feil som kan undersøkes - Ta med type, melding og relevante kontekstfelter
- Legg til
__tostringfor lesbar utskrift - Pakk inn feil for å legge til kontekst uten å miste årsaken
- Velg håndtering etter type: kontroller
err.type, ikke strengmønstre
Lær deg Lua med en AI-veileder – gratis
Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.
- Kurs
- 40
- Leksjoner
- 159
Ofte stilte spørsmål
Er leksjonen «Strukturerte feilobjekter» gratis?
Ja – du kan lese valgfritt 3 av leksjonene i læringsstien Lua Academy, inkludert «Strukturerte feilobjekter», gratis i sin helhet her på nettet. Deretter låser CoddyKit PRO opp alle leksjoner, samt interaktiv øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Kurset i Lua Academy inneholder totalt 4 leksjoner.
Hva lærer jeg i «Strukturerte feilobjekter»?
Send tabeller som feilobjekter for å formidle type og kontekst. Du øver på Lua Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.
Trenger jeg erfaring for å begynne med Lua Academy?
Ingen tidligere erfaring er nødvendig. Lua Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 4 av 4.
Hvor lang tid tar leksjonen «Strukturerte feilobjekter»?
De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.
Kan jeg skrive og kjøre kode i denne Lua Academy-leksjonen?
Ja. Alle Lua Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.
Alle leksjonene i dette kurset
- Funksjonen error()
- Beskyttede kall med pcall
- xpcall og meldingsbehandlere
- Strukturerte feilobjekter