Ответ
Это механизм 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, который никогда не должен сработать). Это сигнал о серьезной ошибке в логике программиста.