Ответ
Это механизм Go для обработки исключительных, непредвиденных ситуаций, которые делают дальнейшее выполнение программы невозможным в текущем контексте.
-
panic
— это встроенная функция, которая останавливает обычное выполнение текущей горутины. Когда функция вызываетpanic
, её выполнение прекращается, все отложенные (defer
) вызовы в этой функции выполняются, после чего функция возвращает управление вызвавшей её функции, где происходит то же самое. Процесс продолжается вверх по стеку вызовов, пока программа не завершится аварийно. -
defer
— это ключевое слово, которое откладывает выполнение вызова функции до тех пор, пока содержащая её функция не завершит свое выполнение (либо черезreturn
, либо из-заpanic
). Отложенные вызовы выполняются в порядке LIFO (Last-In, First-Out) — последняя отложенная функция выполнится первой. -
recover
— это встроенная функция, которая позволяет перехватить управление горутиной, находящейся в состоянии паники.recover
полезна только внутриdefer
-функций. Если текущая горутина не паникует, вызовrecover
вернетnil
. Если же горутина паникует, вызовrecover
перехватит значение, переданное вpanic
, и восстановит нормальное выполнение.
Пример:
func main() {
fmt.Println("Start")
safeDivide(10, 0)
fmt.Println("End")
}
func safeDivide(a, b int) {
defer func() {
// recover работает только внутри defer
if r := recover(); r != nil {
fmt.Printf("Перехвачена паника: %vn", r)
}
}()
result := a / b // Эта строка вызовет панику
fmt.Printf("Результат: %dn", result) // Эта строка не выполнится
}
Вывод:
Start
Перехвачена паника: runtime error: integer divide by zero
End
Когда использовать:
Основное правило — не использовать panic
для обычной обработки ошибок. Для этого в Go есть явный возврат error
.
Допустимые случаи использования panic/recover
:
- Предотвращение падения всего сервера. Например, в веб-сервере одна горутина, обрабатывающая HTTP-запрос, может запаниковать из-за непредвиденной ошибки. С помощью
recover
вdefer
можно перехватить эту панику, записать лог, отдать клиенту ошибку 500, но при этом сам сервер продолжит работать и обслуживать другие запросы. - Ошибки в программе, которые не должны происходить. Например, если программа достигает состояния, которое считается невозможным (например,
case
вswitch
, который никогда не должен сработать). Это сигнал о серьезной ошибке в логике программиста.