Использование `recover`
Часть раздела Логика и управление потоком путешествия по GO на Coddy — урок 43 из 68.
В то время как panic немедленно останавливает вашу программу, Go предоставляет способ восстановить контроль с помощью функции recover. Функция recover позволяет перехватить панику и корректно её обработать, предотвращая аварийное завершение всей программы.
Однако recover имеет очень специфическое требование: она может быть использована только внутри отложенной функции. Когда возникает паника, Go выполняет все отложенные функции перед завершением программы, предоставляя recover возможность перехватить панику:
func riskyFunction() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
}
}()
panic("something went wrong!")
}Функция recover возвращает значение, которое было передано в panic, или nil, если паники не произошло. Это позволяет вам проверить, произошла ли паника, и предпринять соответствующие действия, такие как логирование ошибки или выполнение операций по очистке.
Как и panic, recover следует использовать в Go с осторожностью. Чаще всего это встречается в таких сценариях, как веб-серверы, где необходимо предотвратить падение всего сервера из-за паники в одном запросе, позволяя ему продолжать обработку других запросов.
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Задание
ЛегкоСоздайте обработчик запросов веб-сервера, который использует recover для корректной обработки паник и предотвращения сбоя всего сервера. Эта задача демонстрирует, как использовать recover внутри отложенной функции (deferred function) для перехвата паник и поддержания стабильности сервера.
Вы получите два входных значения:
- Строку, содержащую детали запроса в формате
"endpoint,method,action"(например,"/api/users,GET,process") - Строку, содержащую конфигурацию сервера в формате
"server_name,max_requests"(например,"WebServer,100")
Ваша задача:
- Разобрать первый входной параметр, разделив его по запятым, чтобы получить endpoint, method и action
- Разобрать второй входной параметр, разделив его по запятым, чтобы получить server name и max requests
- Преобразовать строку max requests в целое число
- Создать функцию с именем
handleRequest, которая принимает endpoint, method, action и server name в качестве параметров - Внутри
handleRequestдобавить отложенную функцию (deferred function), которая используетrecoverдля перехвата любых паник:- Если паника перехвачена (recover возвращает не nil), вывести:
"Server [server_name] recovered from panic: [panic_value]" - После обработки паники вывести:
"Request handling completed safely"
- Если паника перехвачена (recover возвращает не nil), вывести:
- После отложенной функции имитировать обработку запроса в зависимости от action:
- Если action равен
"process": вывести"Processing [method] request to [endpoint]" - Если action равен
"panic_nil": вывести"Attempting dangerous operation", затем вызватьpanic("nil pointer access") - Если action равен
"panic_overflow": вывести"Attempting resource allocation", затем вызватьpanic("memory overflow") - Если action равен
"panic_timeout": вывести"Attempting database connection", затем вызватьpanic("connection timeout") - Для любого другого действия: вывести
"Unknown action: [action]", затем вызватьpanic("invalid action")
- Если action равен
- В функции main вывести сообщение о запуске сервера:
"Starting [server_name] with max [max_requests] requests" - Вызвать функцию
handleRequestс разобранными параметрами - После вызова функции вывести статус сервера:
"Server [server_name] is still running" - В конце вывести сводку:
"Server Summary:""Name: [server_name]""Max Requests: [max_requests]""Last Request: [method] [endpoint]""Action Performed: [action]""Status: Operational"
Используйте пакет strings для разделения входных строк по запятым и пакет strconv для преобразования строки max requests в целое число. Эта задача демонстрирует, как recover позволяет серверам корректно обрабатывать неожиданные паники, предотвращая сбой всей системы из-за ошибок в отдельных запросах.
Шпаргалка
Функция recover позволяет перехватить панику и корректно её обработать, предотвращая аварийное завершение программы.
recover можно использовать только внутри отложенной (deferred) функции:
func riskyFunction() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
}
}()
panic("something went wrong!")
}Функция recover возвращает значение, которое было передано в panic, или nil, если паники не произошло. Это позволяет проверить, случилась ли паника, и предпринять соответствующие действия.
recover часто используется в веб-серверах, чтобы паника при обработке одного запроса не приводила к падению всего сервера.
Попробуйте сами
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
// Чтение входных данных
var requestDetails string
var serverConfig string
fmt.Scanln(&requestDetails)
fmt.Scanln(&serverConfig)
// Разбор деталей запроса
requestParts := strings.Split(requestDetails, ",")
endpoint := requestParts[0]
method := requestParts[1]
action := requestParts[2]
// Разбор конфигурации сервера
configParts := strings.Split(serverConfig, ",")
serverName := configParts[0]
maxRequests, _ := strconv.Atoi(configParts[1])
// TODO: Напишите свой код ниже
// Создайте функцию handleRequest с механизмом recover
// Выведите сообщение о запуске сервера
// Вызовите функцию handleRequest
// Выведите статус сервера и сводную информацию
}В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Логика и управление потоком
1Продвинутое управление потоком выполнения
Switch с использованием `fallthrough`Выход из вложенных цикловПродолжение конкретного циклаОператор `goto`Итоги: Продвинутое управление циклами4Проект: Простой список задач
Настройка проектаДобавление задачи7Углубленная обработка ошибок
Пользовательские типы ошибокОбертывание ошибок с помощью `%w`Распаковка с помощью `errors.Is`Распаковка с помощью `errors.As`Понимание `panic`Использование `recover`Итоги: Безопасное деление2Структуры и методы
Определение методов для структурПолучатели по значениюПолучатели по указателюВыбор типа получателяМетоды против функцийИтоги: поведение структур5Карты: подробный разбор
Карты структурУказатели как значения картПроверка карт на nilСравнение картИтоги: счетчик частоты слов3Интерфейсы (Основы)
Что такое интерфейс?Определение интерфейсаРеализация интерфейсаИспользование интерфейсных типовПустой интерфейсУтверждение типаПереключатель типовИтоги: Фигуры и поведение