Strukturerade felobjekt
Skicka tabeller som felobjekt för att förmedla typ och sammanhang.
Strukturerade felobjekt är en gratis lektion i Lua Academy på CoddyKit. Detta är lektion 4 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för Lua Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Lua Academy innehåller totalt 4 lektioner.
Varför strukturerade fel?
Vanliga strängfel är svåra att hantera programmatiskt. Strukturerade felobjekt (tabeller) innehåller typinformation och sammanhangsdata och kan granskas och åtgärdas av anropande kod. Det möjliggör felbaserad dirigering utan strängtolkning.
-- 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 för felkonstruktorer
Skapa en fabriksfunktion för fel för varje feltyp. Fabriken bygger en tabell med konsekventa fält: typ, meddelande och relevant sammanhang. En __tostring-metametod gör att felet skrivs ut på ett tydligt sätt.
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:42Typkontroll av felobjekt
Efter att ni har fångat ett fel kontrollerar ni om det är en tabell med ett känt typfält. På så sätt kan ni välja olika återställningsstrategier utifrån feltypen utan att förlita er på strängmönstermatchning.
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
endFelhierarki
Simulera en felhierarki genom att kontrollera is_a-fält eller använda metatabeller. Underordnade feltyper ärver den överordnade typens fält och kan behandlas som den överordnade typen av kod som inte behöver känna till detaljerna.
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")) -- falseOmsluta fel
När ni fångar och kastar om ett fel kan ni omsluta originalfelet för att lägga till sammanhang utan att förlora det. Omslaget har en egen typ och innehåller originalfelet som orsak.
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))
endFelkoder jämfört med feltyper
Två vanliga konventioner är felkoder (numeriska, till exempel HTTP-statuskoder) och feltypssträngar (semantiska namn). Felkoder är enkla att jämföra numeriskt, medan typssträngar beskriver sig själva. Många system använder båda.
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"))Felstack (orsakskedja)
När ett fel orsakas av ett annat kan ni kedja ihop dem. Det ger en fullständig bild av vad som gick fel på varje lager i applikationen. Packa upp kedjan för att logga eller visa hela felberättelsen.
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 deniedFel i callback-sammanhang
När fel uppstår i callbacks (händelsehanterare, iteratorer) propageras de till den kod som anropade callbacken. Använd pcall för att fånga dem och rapportera med sammanhang om vilken callback som misslyckades.
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)
endSkriva ut feldetaljer
En hjälpfunktion som skriver ut ett felobjekt på ett strukturerat och lättläst sätt och hanterar både sträng- och tabellfel. Detta är användbart vid applikationsgränser där fel loggas eller visas för användare.
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 strukturerade fel
Skapa en assertT (assert med typade fel) som utlöser ett strukturerat fel i stället för en vanlig sträng. Då blir det enkelt för anropande kod att testa specifika feltyper.
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) endSnabbkontroll
Vilken är den främsta fördelen med att skicka en tabell till error() i stället för en sträng?
Sammanfattning: strukturerade fel
Sammanfattning:
- Skicka tabeller till
error()för strukturerade och inspekterbara fel - Inkludera typ, meddelande och relevanta sammanhangsfält
- Lägg till
__tostringför lättläst utskrift - Omslut fel för att lägga till sammanhang utan att förlora orsaken
- Välj åtgärd utifrån typ i hanterare: kontrollera
err.type, inte strängmönster
Lär dig Lua med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 40
- Lektioner
- 159
Vanliga frågor
Är lektionen ”Strukturerade felobjekt” gratis?
Ja – du kan läsa vilka 3 lektioner som helst i lärvägen Lua Academy, inklusive ”Strukturerade felobjekt”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i Lua Academy innehåller totalt 4 lektioner.
Vad lär jag mig i ”Strukturerade felobjekt”?
Skicka tabeller som felobjekt för att förmedla typ och sammanhang. Ni övar på Lua Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig Lua Academy?
Du behöver inga förkunskaper. Utbildningen i Lua Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 4 av 4.
Hur lång tid tar lektionen ”Strukturerade felobjekt”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här Lua Academy-lektionen?
Ja. Varje Lua Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- Funktionen error()
- Skyddade anrop med pcall
- xpcall och meddelandehanterare
- Strukturerade felobjekt