Ответ
Основная задача recover()
— перехватить панику, чтобы предотвратить аварийное завершение программы и выполнить код для graceful shutdown или обработки ошибки.
recover()
эффективно работает только при вызове внутри отложенной функции (defer
), потому что:
- Когда возникает паника, нормальное выполнение функции немедленно прекращается.
- Исполнение переходит к выполнению
defer
функций, которые были отложены в этой горутине. - Только на этом этапе
recover()
может "поймать" панику. Если вызватьrecover()
внеdefer
, он просто вернетnil
, так как в момент его вызова паники еще (или уже) нет.
Пример корректного использования:
func safeFunc() {
defer func() {
// recover() перехватывает значение, переданное в panic()
if r := recover(); r != nil {
fmt.Println("Перехвачена паника:", r)
}
}()
fmt.Println("Начало выполнения safeFunc")
// Симуляция критической ошибки
panic("что-то пошло не так")
// Этот код никогда не выполнится
fmt.Println("Завершение выполнения safeFunc")
}
Ключевые моменты:
- Место вызова:
recover()
должен быть вызван непосредственно изdefer
функции. Вызов из функции, которую вызываетdefer
, не сработает. - Возвращаемое значение: Возвращает значение, переданное в
panic()
, илиnil
, если паники не было. - Продолжение выполнения: После успешного
recover()
паника прекращается, и выполнение продолжается со следующего оператора после вызова функции, в которой произошла паника. Сама запаниковавшая функция не возобновляет свою работу.