Ответ
Функция recover
может перехватить панику только при соблюдении двух ключевых условий:
- Вызов внутри
defer
:recover
должен вызываться непосредственно внутри отложенной (deferred) функции. Если вызвать его в любом другом месте, он вернетnil
и не будет иметь никакого эффекта. - Та же горутина:
recover
может перехватить панику только в той же горутине, в которой она произошла. Паника в одной горутине не может быть перехвачена в другой.
package main
import "fmt"
func main() {
// Пример правильного использования
safeCall()
fmt.Println("Программа продолжает работу после перехвата паники.")
// Паника в main не будет перехвачена, т.к. нет defer с recover
// panic("Эта паника завершит программу")
}
func safeCall() {
// 1. Функция defer будет выполнена при выходе из safeCall, в том числе при панике
defer func() {
// 2. recover перехватывает значение, переданное в panic
if r := recover(); r != nil {
fmt.Printf("Паника перехвачена: %vn", r)
}
}()
fmt.Println("Вызываем функцию, которая может запаниковать...")
causePanic()
fmt.Println("Эта строка не будет выполнена.")
}
func causePanic() {
panic("произошла управляемая паника")
}
Важные моменты:
recover
возвращает значение, переданное вpanic
. Если паники не было,recover
вернетnil
.recover
не может перехватить некоторые фатальные ошибки времени выполнения (например,out of memory
), которые приводят к немедленному завершению программы.