Menu
CoddyTech

Использование `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 следует использовать экономно. Чаще всего его применяют в таких случаях, как работа веб-серверов, когда нужно не допустить, чтобы паника при обработке одного запроса привела к сбою всего сервера, и позволить ему продолжать обслуживать другие запросы.

challenge icon

Задание

Легко

Создай обработчик запросов веб-сервера, который использует recover, чтобы корректно обрабатывать паники и предотвращать сбой всего сервера. В этом задании показано, как использовать recover внутри отложенной функции для перехвата паник и поддержания стабильной работы сервера.

На вход будут поданы две строки:

  • Строка с данными запроса в формате "endpoint,method,action" (например, "/api/users,GET,process")
  • Строка с конфигурацией сервера в формате "server_name,max_requests" (например, "WebServer,100")

Твоя задача:

  1. Разобрать первую строку, разделив её по запятым, чтобы получить конечную точку, метод и действие
  2. Разобрать вторую строку, разделив её по запятым, чтобы получить имя сервера и максимальное количество запросов
  3. Преобразовать строку с максимальным количеством запросов в целое число
  4. Создать функцию с именем handleRequest, принимающую в качестве параметров конечную точку, метод, действие и имя сервера
  5. Внутри handleRequest добавь отложенную функцию, которая использует recover для перехвата любых паник:
    • Если панику удалось перехватить (recover возвращает ненулевое значение), выведи: "Server [server_name] recovered from panic: [panic_value]"
    • После обработки паники выведи: "Request handling completed safely"
  6. После отложенной функции смоделируй обработку запроса в зависимости от действия:
    • Если действие — "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")
  7. В функции main выведи сообщение о запуске сервера: "Starting [server_name] with max [max_requests] requests"
  8. Вызови функцию handleRequest с разобранными параметрами
  9. После вызова функции выведи статус сервера: "Server [server_name] is still running"
  10. В завершение выведи сводку:
    • "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
	// Выведите состояние сервера и сводку
	
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Логика и управление потоком

Потренируйтесь самостоятельно: Онлайн-компилятор Go