Menu
Coddy logo textTech

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

quiz iconПроверьте себя

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

quiz iconПроверьте себя

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

quiz iconПроверьте себя

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

challenge icon

Задание

Легко

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

Вы получите два входных значения:

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

Ваша задача:

  1. Разобрать первый входной параметр, разделив его по запятым, чтобы получить endpoint, method и action
  2. Разобрать второй входной параметр, разделив его по запятым, чтобы получить server name и max requests
  3. Преобразовать строку max requests в целое число
  4. Создать функцию с именем handleRequest, которая принимает endpoint, method, action и server name в качестве параметров
  5. Внутри handleRequest добавить отложенную функцию (deferred function), которая использует recover для перехвата любых паник:
    • Если паника перехвачена (recover возвращает не nil), вывести: "Server [server_name] recovered from panic: [panic_value]"
    • После обработки паники вывести: "Request handling completed safely"
  6. После отложенной функции имитировать обработку запроса в зависимости от 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")
  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 для преобразования строки 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
	// Выведите статус сервера и сводную информацию
	
}
quiz iconПроверьте себя

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

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