Ответ
В Go panic
предназначена для сигнализации о невосстановимых ошибках — таких, которые не должны были произойти в нормальных условиях (например, выход за пределы массива, разыменование nil-указателя). Это не механизм для обработки обычных ошибок (как try-catch
в других языках).
Панику следует перехватывать с помощью recover()
только в строго определенных местах.
Когда и где использовать recover
recover()
всегда используется внутри defer
-функции. Если panic
не было, recover()
вернет nil
.
func safeRun() {
defer func() {
if r := recover(); r != nil {
log.Printf("Перехвачена паника: %vn%s", r, debug.Stack())
}
}()
// Код, который потенциально может запаниковать
mightPanic()
}
Основные сценарии для recover
:
- На верхнем уровне приложения: В функции
main
или в обработчике HTTP-запросов, чтобы паника в одной горутине (например, при обработке одного запроса) не привела к падению всего сервера. Цель — залогировать ошибку и продолжить работу. - В "долгоживущих" горутинах: В воркерах или фоновых задачах, чтобы случайная паника не остановила важный процесс.
- При работе с CGo или сторонними библиотеками: В качестве защитной меры, если есть подозрение, что внешний код может вызвать панику.
Что НЕ следует делать
- Не используйте
panic
/recover
для контроля потока выполнения. Для ожидаемых ошибок (файл не найден, неверный ввод пользователя) всегда возвращайте значение типаerror
. - Библиотечный код не должен паниковать. Хорошая библиотека всегда возвращает ошибки своим пользователям, а не "взрывается". Паника в библиотеке — признак бага.