Go Erros Intermediário
defer, panic e recover
Em Go, defer agenda uma chamada de função para ser executada quando a função que a contém retornar. As chamadas adiadas são empilhadas e executadas na ordem LIFO (último a entrar, primeiro a sair). Isso é muito útil para liberar recursos, como fechar arquivos ou conexões, garantindo que a limpeza ocorra mesmo em caso de erro.
panic interrompe o fluxo normal do programa e começa a desenrolar a pilha, executando os defer pendentes. recover permite capturar um panic e retomar o controle, mas só funciona se for chamado diretamente dentro de uma função adiada (defer).
Quando usados juntos, defer e recover permitem tratar situações excepcionais sem derrubar o programa. No entanto, panic deve ser reservado para erros irrecuperáveis ou violações de invariantes, não para controle de fluxo comum.
É importante lembrar que recover não funciona se o panic ocorrer em uma goroutine diferente da que chama recover. Cada goroutine precisa de seu próprio tratamento.
Pontos-chave
deferexecuta a função adiada quando a função atual retorna, na ordem LIFO.- Argumentos de uma chamada
defersão avaliados no momento em que odeferé declarado. recoversó tem efeito se chamado diretamente dentro de uma função adiada.- Um
panicnão capturado em uma goroutine derruba todo o programa. - Use
panicapenas para erros irrecuperáveis; para erros esperados, retorneerror.
package main
import (
"fmt"
)
func main() {
// Exemplo 1: ordem LIFO
defer fmt.Println("primeiro defer (executa por último)")
defer fmt.Println("segundo defer")
defer fmt.Println("terceiro defer (executa primeiro)")
// Exemplo 2: defer com closure e recover
func() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recuperado de:", r)
}
}()
panic("algo deu errado")
}()
// Exemplo 3: recover em goroutine separada
done := make(chan bool)
go func() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recuperado na goroutine:", r)
}
done <- true
}()
panic("panic na goroutine")
}()
<-done
fmt.Println("Fim do programa")
}