Lua Academy · Aula

Chamadas protegidas com pcall

Capture erros com segurança usando pcall e interprete os valores retornados.

Aula 2 de 412 etapas

Chamadas protegidas com pcall é uma aula grátis de Lua Academy no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Lua Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Lua Academy inclui 4 aulas no total.

Noções básicas de pcall

pcall(f, ...) chama a função f com os argumentos ... em modo protegido. Se f for concluída com sucesso, pcall retorna true seguido de todos os valores retornados. Se f gerar um erro, pcall retorna false seguido da mensagem de erro. O programa continua de qualquer forma.

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

Captura de erros específicos

Verifique o tipo do valor do erro após pcall para tratar diferentes tipos de erro de maneiras diferentes. Erros em tabelas contêm dados estruturados; erros em strings contêm uma mensagem. Sempre trate os dois casos.

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

Vários valores retornados em caso de sucesso

Em caso de sucesso, pcall retorna todos os valores retornados pela função protegida depois do true inicial. Capture-os com várias variáveis.

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

Aninhamento de pcall

As chamadas de pcall podem ser aninhadas. Cada pcall cria um escopo protegido independente. Um erro em um pcall interno é capturado pelo pcall interno, não pelo externo. Isso permite implementar estratégias de contingência.

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 com métodos

Para chamar um método (sintaxe com dois-pontos) por meio de pcall, passe a função e o objeto como primeiro argumento. pcall(obj.method, obj, args...) ou envolva a chamada em um fechamento.

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 para segurança de E/S

Envolva as operações de E/S em pcall para capturar erros inesperados do OS. Retorne um par consistente de resultado e erro para que os chamadores possam tratar as falhas com elegância.

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

Padrão de repetição com pcall

Repita uma operação instável (uma solicitação de rede ou gravação de arquivo) até N vezes, usando pcall para capturar os erros. Em código real, aguarde entre as tentativas (ou use corrotinas).

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)

Armazenamento de resultados de pcall em uma tabela

Quando pcall é usado em um laço, armazene os resultados em uma tabela para analisá-los posteriormente. Isso é útil em operações em lote nas quais você deseja processar todos os itens e coletar os erros, em vez de parar na primeira falha.

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 versus xpcall

pcall captura o erro, mas fornece apenas o valor do erro. xpcall permite fornecer uma função manipuladora de mensagens que é executada enquanto a pilha ainda está intacta, possibilitando rastreamentos da pilha. Escolha xpcall quando precisar de rastreamentos.

-- 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

Convenção de retorno de pcall

Use pcall como base para uma API consistente: sempre retorne value em caso de sucesso ou nil, errorMessage em caso de falha. Estruture suas funções dessa maneira para que os chamadores sempre saibam o que esperar.

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

Verificação rápida

O que pcall retorna quando a função protegida é concluída com sucesso?

Recapitulação: pcall

Resumo:

  • pcall(f, ...) → true, results... ou false, err
  • Verifique o primeiro retorno para determinar sucesso ou falha
  • Em caso de sucesso, há vários valores retornados depois de true
  • pcall aninhado: cada chamada captura seus próprios erros de forma independente
  • Padrão de repetição: use um laço com pcall para operações instáveis
  • Use xpcall quando precisar de rastreamentos da pilha
Grátis para começar

Aprenda Lua com um tutor de IA — grátis

Escreva e execute código real no seu navegador, obtenha ajuda instantânea de um tutor de IA 24/7 e continue de onde parou na web ou no app.

Cursos
40
Aulas
159

Perguntas Frequentes

A aula “Chamadas protegidas com pcall” é grátis?

Sim — o texto completo de “Chamadas protegidas com pcall” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Lua Academy, atualize para CoddyKit PRO. O curso de Lua Academy inclui 4 aulas no total.

O que vou aprender em “Chamadas protegidas com pcall”?

Capture erros com segurança usando pcall e interprete os valores retornados. Você pratica Lua Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Lua Academy?

Nenhuma experiência prévia é necessária. Lua Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.

Quanto tempo leva a aula “Chamadas protegidas com pcall”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Lua Academy?

Sim. Cada aula de Lua Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. A função error()
  2. Chamadas protegidas com pcall
  3. xpcall e manipuladores de mensagens
  4. Objetos de erro estruturados
← Voltar para Lua Academy