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

Что такое recovery в Go?

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

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

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

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

Что такое Recovery в Go?

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

Как работает механизм Recovery?

Функция recover() возвращает значение, которое было передано в вызов panic(), и восстанавливает нормальное выполнение программы. Важные особенности:

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

Базовый пример использования

package main

import "fmt"

func safeFunction() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Перехвачена паника:", r)
        }
    }()
    
    panic("критическая ошибка!")
    fmt.Println("Этот код не выполнится")
}

func main() {
    safeFunction()
    fmt.Println("Программа продолжает работу после recovery")
}

Практические сценарии применения

  1. Обработка ошибок в горутинах — предотвращение падения всей программы из-за сбоя в одной горутине:
func worker() {
    defer func() {
        if r := recover(); r != nil {
            log.Printf("Горутина восстановлена: %v", r)
        }
    }()
    // Код, который может вызвать панику
}
  1. Веб-серверы и обработчики HTTP — обеспечение доступности сервера даже при ошибках:
func handler(w http.ResponseWriter, r *http.Request) {
    defer func() {
        if r := recover(); r != nil {
            http.Error(w, "Внутренняя ошибка сервера", http.StatusInternalServerError)
            log.Printf("Паника в обработчике: %v", r)
        }
    }()
    // Обработка запроса
}
  1. Обработка внешних зависимостей — защита от сбоев в сторонних библиотеках:
func safeExternalCall() (result interface{}, err error) {
    defer func() {
        if r := recover(); r != nil {
            err = fmt.Errorf("внешний вызов вызвал панику: %v", r)
        }
    }()
    result = potentiallyDangerousLibraryCall()
    return
}

Важные принципы использования Recovery

Лучшие практики:

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

Что следует избегать:

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

Отличия от обычной обработки ошибок

В Go существует чёткое разделение:

  • Ошибки (errors) — ожидаемые проблемы, которые обрабатываются через возвращаемые значения
  • Паники (panic) — непредвиденные, критические ситуации
  • Recovery — "аварийный люк" для паник, а не механизм ежедневной обработки ошибок

Заключение

Recovery — это мощный инструмент для повышения отказоустойчивости Go-приложений, но требующий взвешенного подхода. Правильное использование этого механизма позволяет создавать стабильные системы, которые могут переживать неожиданные сбои без полного прекращения работы. Ключевое правило — восстанавливаться только там, где это имеет смысл, и всегда обеспечивать логирование для диагностики корневых причин паник.

Что такое recovery в Go? | PrepBro