Lua Academy · Lektion

Skyddade anrop med pcall

Fånga fel säkert med pcall och tolka returvärdena.

Lektion 2 av 412 steg

Skyddade anrop med pcall är en gratis lektion i Lua Academy på CoddyKit. Detta är lektion 2 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.

Grunderna i pcall

pcall(f, ...) anropar funktionen f med argumenten ... i skyddat läge. Om f lyckas returnerar pcall true följt av alla returvärden. Om f ger ett fel returnerar pcall false följt av felmeddelandet. Programmet fortsätter i båda fallen.

local function risky(x)
  if x < 0 then error("negative input: " .. x) end
  return math.sqrt(x)
end

local ok, result = pcall(risky, 9)
print(ok, result)    -- true  3.0

ok, result = pcall(risky, -1)
print(ok, result)    -- false  ...: negative input: -1

Fånga specifika fel

Kontrollera felvärdets typ efter pcall för att hantera olika feltyper på olika sätt. Tabellfel innehåller strukturerade data, medan strängfel innehåller ett meddelande. Hantera alltid båda fallen.

local function op(errType)
  if errType == "table" then
    error({code=42, msg="structured error"})
  else
    error("plain string error")
  end
end

local ok, err = pcall(op, "table")
if not ok then
  if type(err) == "table" then
    print("Code:", err.code, "Msg:", err.msg)
  else
    print("String error:", err)
  end
end

Flera returvärden vid lyckat resultat

Vid lyckat resultat returnerar pcall alla den skyddade funktionens returvärden efter det inledande true. Fånga dem i flera variabler.

local function compute(a, b)
  return a + b, a * b, a - b
end

local ok, sum, product, diff = pcall(compute, 6, 4)
if ok then
  print("sum:", sum, "product:", product, "diff:", diff)
  -- sum: 10  product: 24  diff: 2
end

Kapsla pcall

pcall-anrop kan kapslas i varandra. Varje pcall skapar ett oberoende skyddat område. Ett fel i en inre pcall fångas av den inre pcall-en, inte den yttre. På så sätt kan ni implementera reservstrategier.

local function tryPrimary()
  error("primary failed")
end

local function tryFallback()
  return "fallback result"
end

local ok, result = pcall(tryPrimary)
if not ok then
  print("Primary failed:", result)
  ok, result = pcall(tryFallback)
end

if ok then print("Got:", result) end  -- fallback result

pcall med metoder

För att anropa en metod (kolonsyntax) via pcall skickar ni funktionen och objektet som det första argumentet. pcall(obj.method, obj, args...) eller så omsluter ni anropet i en closure.

local obj = {
  x = 10,
  compute = function(self, n)
    if n == 0 then error("zero divisor") end
    return self.x / n
  end
}

-- Pass method + self explicitly
local ok, v = pcall(obj.compute, obj, 2)
print(ok, v)   -- true  5.0

-- Or use a closure
ok, v = pcall(function() return obj:compute(0) end)
print(ok, v)   -- false  ...zero divisor

pcall för säker I/O

Omslut I/O-operationer med pcall för att fånga oväntade fel från operativsystemet. Returnera alltid ett konsekvent resultat-/felpar så att anropande kod kan hantera misslyckanden på ett bra sätt.

local function safeRead(path)
  local ok, result = pcall(function()
    local f = assert(io.open(path, "r"))
    local content = f:read("a")
    f:close()
    return content
  end)
  if ok then return result
  else return nil, result
  end
end

local data, err = safeRead("config.txt")
if data then print("Read", #data, "bytes")
else print("Error:", err)
end

Försöksmönster med pcall

Försök utföra en instabil operation (nätverksförfrågan, filskrivning) upp till N gånger och använd pcall för att fånga fel. Vänta mellan försöken i verklig kod (eller använd coroutines).

local function retry(fn, maxAttempts)
  local attempts = 0
  while attempts < maxAttempts do
    attempts = attempts + 1
    local ok, result = pcall(fn)
    if ok then
      print("Succeeded on attempt", attempts)
      return result
    end
    print("Attempt", attempts, "failed:", result)
  end
  error("all " .. maxAttempts .. " attempts failed")
end

local n = 0
retry(function()
  n = n + 1
  if n < 3 then error("not ready") end
  return "done"
end, 5)

Samla pcall-resultat i en tabell

När pcall används i en loop kan ni spara resultaten i en tabell för senare analys. Detta är användbart vid batchåtgärder där ni vill behandla alla objekt och samla in fel i stället för att avbryta vid det första misslyckandet.

local jobs = {10, -5, 25, 0, 16}
local results = {}

for _, n in ipairs(jobs) do
  local ok, v = pcall(function()
    if n < 0 then error("negative") end
    return math.sqrt(n)
  end)
  results[#results+1] = {input=n, ok=ok, value=v}
end

for _, r in ipairs(results) do
  if r.ok then
    print(r.input, "->", string.format("%.3f", r.value))
  else
    print(r.input, "-> ERROR:", r.value)
  end
end

pcall jämfört med xpcall

pcall fångar felet men ger er endast felvärdet. xpcall låter er ange en meddelandehanterarfunktion som körs medan stacken fortfarande är intakt, vilket möjliggör stackspårningar. Välj xpcall när ni behöver traceback-information.

-- pcall: simple, no traceback
local ok1, err1 = pcall(function()
  error("simple error")
end)
print(err1)   -- only the error message

-- xpcall: with traceback handler
local ok2, err2 = xpcall(
  function() error("traced error") end,
  function(e) return debug.traceback(e, 2) end
)
print(err2)   -- full stack trace

pcalls returkonvention

Använd pcall som grund för ett konsekvent API: returnera alltid value vid lyckat resultat eller nil, errorMessage vid fel. Bygg era funktioner på detta sätt så att anropande kod alltid vet vad den kan förvänta sig.

local function loadJSON(path)
  local ok, result = pcall(function()
    local f = assert(io.open(path, "r"))
    local text = f:read("a")
    f:close()
    -- Fake JSON parse for demo
    return {data = text, path = path}
  end)
  if ok then return result
  else return nil, result
  end
end

local data, err = loadJSON("data.json")
if data then print("Loaded:", data.path)
else print("Failed:", err)
end

Snabbkontroll

Vad returnerar pcall när den skyddade funktionen lyckas?

Sammanfattning: pcall

Sammanfattning:

  • pcall(f, ...) → true, results... eller false, err
  • Kontrollera det första returvärdet för att avgöra om anropet lyckades eller misslyckades
  • Vid lyckat resultat kommer flera returvärden efter true
  • Kapslad pcall: varje anrop fångar sina egna fel oberoende av de andra
  • Försöksmönster: använd en loop med pcall för instabila operationer
  • Använd xpcall när ni behöver stackspårningar
Gratis att börja

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 ”Skyddade anrop med pcall” gratis?

Ja – du kan läsa vilka 3 lektioner som helst i lärvägen Lua Academy, inklusive ”Skyddade anrop med pcall”, 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 ”Skyddade anrop med pcall”?

Fånga fel säkert med pcall och tolka returvärdena. 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 2 av 4.

Hur lång tid tar lektionen ”Skyddade anrop med pcall”?

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

  1. Funktionen error()
  2. Skyddade anrop med pcall
  3. xpcall och meddelandehanterare
  4. Strukturerade felobjekt
← Tillbaka till Lua Academy