panic, recover e defer
Saiba quando usar panic e como recuperar-se de forma adequada
panic, recover e defer é uma aula grátis de Go Academy no CoddyKit. Esta é a aula 4 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 Go Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Go Academy inclui 4 aulas no total.
O que é pânico?
panic interrompe a execução normal da goroutine atual, desfaz a pilha de chamadas executando as funções adiadas e encerra o programa se não for recuperado:
package main
import "fmt"
func mustPositive(n int) int {
if n <= 0 {
panic(fmt.Sprintf("mustPositive: got %d", n))
}
return n
}
func main() {
fmt.Println(mustPositive(5)) // 5
// fmt.Println(mustPositive(-1)) // panics!
}Quando usar pânico
Use panic somente para:
- Erros de programação realmente irrecuperáveis (invariantes violadas)
- Condições impossíveis que indicam um erro
- Falhas na inicialização (configuração ausente, conexões que falharam durante a inicialização)
Nunca use pânico para condições de falha esperadas — use error em vez disso.
Noções básicas de defer
defer agenda uma chamada de função para ser executada quando a função envolvente retornar, independentemente de como ela retorne (normalmente, com erro ou com pânico):
package main
import "fmt"
func main() {
defer fmt.Println("third")
defer fmt.Println("second") // LIFO order
defer fmt.Println("first")
fmt.Println("running...")
// Output:
// running...
// first
// second
// third
}defer para limpeza
O uso mais comum de defer é garantir que os recursos sejam liberados:
package main
import ("fmt"; "os")
func readFile(path string) (string, error) {
f, err := os.Open(path)
if err != nil {
return "", fmt.Errorf("open: %w", err)
}
defer f.Close() // always runs, even if we return early
buf := make([]byte, 1024)
n, _ := f.Read(buf)
return string(buf[:n]), nil
}recover — captura de pânicos
recover interrompe um pânico e retorna o valor do pânico. Ele deve ser chamado diretamente dentro de uma função defer:
package main
import "fmt"
func safeDiv(a, b int) (result int, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("recovered from panic: %v", r)
}
}()
return a / b, nil // panics if b==0
}
func main() {
r, err := safeDiv(10, 0)
fmt.Println(r, err)
// 0 recovered from panic: runtime error: integer divide by zero
}recover deve estar em uma função adiada
recover só funciona quando chamado diretamente dentro de uma função adiada. Chamá-lo em outro lugar retorna nil:
package main
import "fmt"
func wrong() {
// recover() here does nothing — not in defer
}
func correct() {
defer func() {
if r := recover(); r != nil {
fmt.Println("caught:", r)
}
}()
panic("oops")
}
func main() { correct() }Pânico no código de biblioteca
O código de biblioteca quase nunca deve permitir que pânicos escapem para os chamadores. Converta pânicos em erros na fronteira:
package main
import ("fmt"; "runtime/debug")
func safeCall(fn func()) (err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("panic: %v\n%s", r, debug.Stack())
}
}()
fn()
return nil
}
func main() {
err := safeCall(func() { panic("boom") })
fmt.Println(err != nil) // true
}Ordem LIFO de defer e armadilha em laços
As chamadas adiadas são executadas na ordem último a entrar, primeiro a sair (LIFO). Tenha cuidado ao adiar chamadas dentro de laços — use uma função anônima ou uma função auxiliar:
package main
import "fmt"
func processFiles(names []string) {
for _, name := range names {
name := name // capture loop variable
defer func() { fmt.Println("close:", name) }()
}
}
func main() {
processFiles([]string{"a.txt", "b.txt", "c.txt"})
// Output (LIFO): close: c.txt, close: b.txt, close: a.txt
}defer com valores de retorno nomeados
As funções adiadas podem ler e modificar valores de retorno nomeados — útil para anotar erros:
package main
import "fmt"
func doWork() (err error) {
defer func() {
if err != nil {
err = fmt.Errorf("doWork: %w", err)
}
}()
return fmt.Errorf("something failed")
}
func main() {
err := doWork()
fmt.Println(err) // doWork: something failed
}pânico versus erro: guia de decisão
Escolha entre pânico e erro:
- Use error: falhas esperadas (arquivo não encontrado, tempo limite da rede, entrada inválida)
- Use panic: erros de programação (acesso a mapa nulo, índice fora dos limites), estados impossíveis e falhas de inicialização
- Nunca use pânico através das fronteiras da API — os chamadores não conseguem tratá-lo
- Recupere pânicos no nível superior da goroutine em servidores para evitar encerramentos
Verificação rápida
Onde recover() deve ser chamado para capturar um pânico?
Recapitulação: panic, recover e defer
Resumo:
panic: desenrola a pilha, executa as funções adiadas e encerra o programa se não for recuperadodefer: é executado ao sair da função (normalmente, por erro ou por pânico); na ordem LIFOrecover: interrompe o pânico e retorna um valor; deve estar emdefer- Utilize panic para erros de programação, não para falhas esperadas
- Converta pânicos em erros nos limites da API
Perguntas Frequentes
A aula “panic, recover e defer” é grátis?
Sim — o texto completo de “panic, recover e defer” é 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 Go Academy, atualize para CoddyKit PRO. O curso de Go Academy inclui 4 aulas no total.
O que vou aprender em “panic, recover e defer”?
Saiba quando usar panic e como recuperar-se de forma adequada Você pratica Go 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 Go Academy?
Nenhuma experiência prévia é necessária. Go 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 4 de 4.
Quanto tempo leva a aula “panic, recover e defer”?
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 Go Academy?
Sim. Cada aula de Go 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
- A interface error
- Criando errors personalizados
- Envolvendo e desembrulhando errors
- panic, recover e defer