Использование `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 внутри отложенной функции для перехвата паник и поддержания стабильной работы сервера.
На вход будут поданы две строки:
- Строка с данными запроса в формате
"endpoint,method,action"(например,"/api/users,GET,process") - Строка с конфигурацией сервера в формате
"server_name,max_requests"(например,"WebServer,100")
Твоя задача:
- Разобрать первую строку, разделив её по запятым, чтобы получить конечную точку, метод и действие
- Разобрать вторую строку, разделив её по запятым, чтобы получить имя сервера и максимальное количество запросов
- Преобразовать строку с максимальным количеством запросов в целое число
- Создать функцию с именем
handleRequest, принимающую в качестве параметров конечную точку, метод, действие и имя сервера - Внутри
handleRequestдобавь отложенную функцию, которая используетrecoverдля перехвата любых паник:- Если панику удалось перехватить (recover возвращает ненулевое значение), выведи:
"Server [server_name] recovered from panic: [panic_value]" - После обработки паники выведи:
"Request handling completed safely"
- Если панику удалось перехватить (recover возвращает ненулевое значение), выведи:
- После отложенной функции смоделируй обработку запроса в зависимости от действия:
- Если действие —
"process": выведи"Processing [method] request to [endpoint]" - Если действие —
"panic_nil": выведи"Attempting dangerous operation", затем вызовиpanic("nil pointer access") - Если действие —
"panic_overflow": выведи"Attempting resource allocation", затем вызовиpanic("memory overflow") - Если действие —
"panic_timeout": выведи"Attempting database connection", затем вызовиpanic("connection timeout") - Для любого другого действия выведи
"Unknown action: [action]", затем вызовиpanic("invalid 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 — чтобы преобразовать строку с максимальным количеством запросов в целое число. В этом задании показано, как 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Сравнение картПовторение — счётчик частоты слов8Проект: простой складской учёт
Обзор проектаПроверка запасов3Интерфейсы (основы)
Что такое интерфейс?Определение интерфейсаРеализация интерфейсаИспользование типов интерфейсовПустой интерфейсУтверждения типовПереключатель типовПовторение — формы и поведениеПотренируйтесь самостоятельно: Онлайн-компилятор Go