← Назад к вопросам

Что делает recovery?

2.0 Middle🔥 71 комментариев
#Основы Go

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Роль и принцип работы recover()

recover() — это встроенная функция в Go, предназначенная для перехвата паники (panic) и восстановления нормального выполнения программы. Она работает исключительно в связке с defer, так как может корректно обработать панику только внутри отложенных функций.

Основное назначение

Когда в Go происходит panic, выполнение текущей функции немедленно прекращается, начинается раскрутка стека (вызов всех отложенных через defer функций), и программа аварийно завершается, если паника не была перехвачена. recover() позволяет:

  1. Перехватить значение паники и получить информацию об ошибке.
  2. Остановить раскрутку стека и вернуть управление в вызывающую функцию.
  3. Предотвратить аварийное завершение программы, обеспечивая контролируемую обработку критических ошибок.

Синтаксис и использование

package main

import "fmt"

func mayPanic() {
    panic("something went wrong")
}

func safeCaller() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered from panic:", r)
        }
    }()
    mayPanic()
    fmt.Println("This line won't be executed")
}

func main() {
    safeCaller()
    fmt.Println("Program continues normally")
}

Вывод:

Recovered from panic: something went wrong
Program continues normally

Ключевые правила работы

  • Работает только внутри defer: Вызов recover() вне отложенной функции не даст эффекта и вернёт nil.
  • Возвращает значение паники: Если паники не было, возвращает nil.
  • Восстанавливает выполнение: После успешного recover() выполнение продолжается с момента, где был вызван defer, а не с места паники.

Типичные сценарии применения

  1. Обработка непредвиденных ошибок в сторонних библиотеках, которые могут вызывать panic.
  2. Защита main() или критических горутин от аварийного завершения всего приложения.
  3. Грациозное завершение ресурсов: даже при панике можно гарантировать закрытие файлов, соединений и т.д.
  4. Веб-серверы: предотвращение остановки сервера из-за паники в одном обработчике запроса.

Пример в контексте HTTP-сервера

func safeHandler(w http.ResponseWriter, r *http.Request) {
    defer func() {
        if err := recover(); err != nil {
            log.Printf("Panic recovered: %v", err)
            http.Error(w, "Internal Server Error", http.StatusInternalServerError)
        }
    }()
    
    // Код обработчика, который может вызывать панику
    processRequest(r)
}

Важные ограничения и лучшие практики

  • Не маскируйте паники без логирования: Всегда логируйте факт восстановления для диагностики.
  • Используйте умеренно: recover() — не замена обычной обработке ошибок через error. Паника предназначена для действительно исключительных ситуаций.
  • Восстанавливайте только там, где это осмысленно: Например, на границах модулей или в корневых горутинах.

Отличие от обработки ошибок

В отличие от обычного возврата error, panic указывает на ситуацию, которую программа не может осмысленно обработать в текущем контексте (например, нулевой указатель, деление на ноль). recover() предоставляет механизм "последнего шанса" для обработки таких катастрофических сбоев.

Таким образом, recover() — это инструмент для создания отказоустойчивых приложений, позволяющий контролировать выполнение даже при возникновении критических ошибок, но требующий взвешенного и аккуратного применения.

Что делает recovery? | PrepBro