Da trilha de Go Este conceito ainda não saiu como card do dia. ir para o card de hoje

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

  • defer executa a função adiada quando a função atual retorna, na ordem LIFO.
  • Argumentos de uma chamada defer são avaliados no momento em que o defer é declarado.
  • recover só tem efeito se chamado diretamente dentro de uma função adiada.
  • Um panic não capturado em uma goroutine derruba todo o programa.
  • Use panic apenas para erros irrecuperáveis; para erros esperados, retorne error.
defer_panic_recover.go
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")
}

Exercícios

  1. 1
    Fácil

    Ordem LIFO com defer

    Escreva um programa que use defer para imprimir as mensagens A, B e C na ordem inversa de declaração. O programa deve declarar três defer consecutivos e, em seguida, imprimir Fim.

    Resolver
  2. 2
    Médio

    Recover em função com defer

    Crie uma função safeDivide(a, b int) (result int, err error) que divide a por b. Se b for zero, a função deve entrar em panic e, usando defer e recover, capturar o panic e retornar um erro com a mensagem "divisão por zero". Caso contrário, retorne o resultado e nil.

    Resolver
  3. 3
    Desafio

    Recover em goroutine com channel

    Implemente uma função worker(id int, jobs <-chan int, results chan<- string) que processa números recebidos do channel jobs. Para cada job, se o número for negativo, a função deve entrar em panic com a mensagem "job negativo: -X". Use defer e recover dentro da goroutine para capturar o panic e enviar uma mensagem de erro para results no formato "worker <id>: erro: job negativo: -X". Para jobs não negativos, envie "worker <id>: job <X> processado". O main deve criar 2 workers, enviar os jobs [1, -2, 3, -4, 5] e imprimir todos os resultados na ordem em que chegarem (use um WaitGroup ou um channel de sincronização).

    Resolver

Continue estudando