0Pricing
Go Academy · Aula

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 recuperado
  • defer: é executado ao sair da função (normalmente, por erro ou por pânico); na ordem LIFO
  • recover: interrompe o pânico e retorna um valor; deve estar em defer
  • 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

  1. A interface error
  2. Criando errors personalizados
  3. Envolvendo e desembrulhando errors
  4. panic, recover e defer
← Voltar para Go Academy