Usando o `recover`
Parte da seção Lógica & Fluxo do Journey de GO da Coddy — lição 43 de 68.
Enquanto o panic interrompe seu programa imediatamente, o Go fornece uma maneira de recuperar o controle por meio da função recover. A função recover permite que você capture um panic e o trate de forma adequada, evitando que todo o seu programa falhe.
No entanto, o recover tem um requisito muito específico: ele só pode ser usado dentro de uma função adiada (deferred function). Quando ocorre um panic, o Go executa todas as funções adiadas antes que o programa termine, dando ao recover a chance de interceptar o panic:
func riskyFunction() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
}
}()
panic("something went wrong!")
}A função recover retorna o valor que foi passado para panic, ou nil se nenhum pânico ocorreu. Isso permite que você verifique se um pânico ocorreu e tome a ação apropriada, como registrar o erro ou realizar operações de limpeza.
Assim como o panic, o recover deve ser usado com moderação em Go. É mais comumente visto em cenários como servidores web, onde você deseja evitar que o pânico de uma única requisição derrube o servidor inteiro, permitindo que ele continue atendendo a outras requisições.
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Desafio
FácilCrie um manipulador de requisições de servidor web que use recover para lidar graciosamente com panics e evitar que o servidor inteiro trave. Este desafio demonstra como usar recover dentro de uma função adiada (deferred function) para capturar panics e manter a estabilidade do servidor.
Você receberá duas entradas:
- Uma string contendo os detalhes da requisição no formato
"endpoint,method,action"(ex:"/api/users,GET,process") - Uma string contendo a configuração do servidor no formato
"server_name,max_requests"(ex:"WebServer,100")
Sua tarefa é:
- Analise a primeira entrada dividindo-a por vírgulas para obter endpoint, method e action
- Analise a segunda entrada dividindo-a por vírgulas para obter o nome do servidor e o máximo de requisições
- Converta a string de máximo de requisições para um número inteiro
- Crie uma função chamada
handleRequestque receba endpoint, method, action e o nome do servidor como parâmetros - Dentro de
handleRequest, adicione uma função adiada (deferred function) que userecoverpara capturar quaisquer panics:- Se um panic for recuperado (recover retorna não-nulo), imprima:
"Server [server_name] recovered from panic: [panic_value]" - Após lidar com o panic, imprima:
"Request handling completed safely"
- Se um panic for recuperado (recover retorna não-nulo), imprima:
- Após a função adiada, simule o processamento da requisição com base na action:
- Se action for
"process": imprima"Processing [method] request to [endpoint]" - Se action for
"panic_nil": imprima"Attempting dangerous operation"e então chamepanic("nil pointer access") - Se action for
"panic_overflow": imprima"Attempting resource allocation"e então chamepanic("memory overflow") - Se action for
"panic_timeout": imprima"Attempting database connection"e então chamepanic("connection timeout") - Para qualquer outra action: imprima
"Unknown action: [action]"e então chamepanic("invalid action")
- Se action for
- Na função main, imprima a mensagem de inicialização do servidor:
"Starting [server_name] with max [max_requests] requests" - Chame a função
handleRequestcom os parâmetros analisados - Após a chamada da função, imprima o status do servidor:
"Server [server_name] is still running" - Finalmente, imprima um resumo:
"Server Summary:""Name: [server_name]""Max Requests: [max_requests]""Last Request: [method] [endpoint]""Action Performed: [action]""Status: Operational"
Use o pacote strings para dividir as strings de entrada por vírgulas e o pacote strconv para converter a string de máximo de requisições em um número inteiro. Este desafio demonstra como o recover permite que os servidores lidem com panics inesperados de forma graciosa, evitando que falhas em requisições individuais derrubem todo o sistema.
Folha de consulta
A função recover permite capturar um pânico e lidar com ele de forma graciosa, evitando que seu programa trave.
recover só pode ser usado dentro de uma função adiada (deferred):
func riskyFunction() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
}
}()
panic("something went wrong!")
}A função recover retorna o valor que foi passado para panic, ou nil se nenhum pânico ocorreu. Isso permite que você verifique se um pânico aconteceu e tome a ação apropriada.
recover é comumente usado em servidores web para evitar que o pânico de uma única requisição trave o servidor inteiro.
Experimente você mesmo
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
// Ler a entrada
var requestDetails string
var serverConfig string
fmt.Scanln(&requestDetails)
fmt.Scanln(&serverConfig)
// Analisar detalhes da requisição
requestParts := strings.Split(requestDetails, ",")
endpoint := requestParts[0]
method := requestParts[1]
action := requestParts[2]
// Analisar configuração do servidor
configParts := strings.Split(serverConfig, ",")
serverName := configParts[0]
maxRequests, _ := strconv.Atoi(configParts[1])
// TODO: Escreva seu código abaixo
// Criar a função handleRequest com mecanismo de recuperação (recover)
// Imprimir mensagem de inicialização do servidor
// Chamar a função handleRequest
// Imprimir o status do servidor e o resumo
}Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Lógica & Fluxo
1Fluxo de Controle Avançado
Switch com `fallthrough`Interrompendo Loops AninhadosContinuando um Loop EspecíficoA Instrução `goto`Recapitulação - Controle de Loop Avançado4Projeto: Lista de Tarefas Simples
Configuração do ProjetoAdicionando uma Tarefa7Tratamento de Erros em Profundidade
Tipos de Erro PersonalizadosWrapping de Erros com `%w`Unwrapping com `errors.Is`Unwrapping com `errors.As`Entendendo o `panic`Usando o `recover`Recapitulação - Divisão Segura2Structs e Métodos
Definindo Métodos em StructsRecebedores de ValorRecebedores de PonteiroEscolhendo RecebedoresMétodos vs FunçõesRecapitulação - Comportamento de Structs5Mapas em Profundidade
Mapas de StructsPonteiros como Valores de MapVerificando Mapas NilComparando MapasRecapitulação - Contador de Frequência de Palavras3Interfaces (O Básico)
O que é uma Interface?Definindo uma InterfaceImplementando uma InterfaceUsando Tipos de InterfaceInterface VaziaAsserções de TipoType SwitchRecapitulação - Formas e Comportamentos