Ответ
Да, обработка паники с помощью defer
и recover
— это основной и идиоматичный механизм в Go для перехвата и обработки критических ошибок.
Механизм работает так:
defer
гарантирует, что вызов функции будет выполнен перед выходом из текущей функции, независимо от того, завершается она нормально или из-за паники.recover()
— это встроенная функция, которая останавливает панику и возвращает значение, с которым была вызванаpanic
. Если паники не было,recover()
возвращаетnil
.
package main
import "fmt"
func main() {
fmt.Println("Начало выполнения main")
safeCall()
fmt.Println("main успешно завершена")
}
func safeCall() {
// Эта отложенная функция будет вызвана перед выходом из safeCall
defer func() {
// recover() перехватывает панику
if r := recover(); r != nil {
fmt.Printf("Перехвачена паника: %vn", r)
}
}()
fmt.Println("Вызов опасной функции...")
panickingFunction()
fmt.Println("Этот код не будет выполнен")
}
func panickingFunction() {
panic("произошла критическая ошибка")
}
Важные правила:
recover()
эффективно работает только когда вызывается напрямую из отложенной функции (defer
). Вызовrecover()
в любом другом месте вернетnil
.recover()
перехватывает панику только в той же горутине, где она произошла. Панику из другой горутины перехватить таким образом нельзя.
Этот механизм позволяет «превратить» панику в обычную ошибку, предотвращая аварийное завершение всей программы и позволяя функции-обертке обработать сбой более грациозно.