Материал проходит вычитку — возможны неточности.
Урок 57 из 118

panic(nil) и re-panic †

Старая библиотека разбора паниковала по-особому: пустым значением, и перехват не мог отличить падение от спокойного выхода. Миша не стал глотать чужую панику и пробросил её дальше по стеку.

Главная мысль

panic(nil) с Go 1.21 отличим от «паники не было», а необработанную чужую панику бросают дальше через re-panic.

Panic(nil)

До Go 1.21 recover возвращал nil и когда паники нет, и при panic(nil) — отличить одно от другого было невозможно. С Go 1.21 panic(nil) передаёт в recover не nil, а *runtime.PanicNilError. Теперь проверка recover != nil честно означает «паника была».

Go

Re-panic

Иногда поймать панику — не значит её обработать. Если defer понял, что эта паника не его, он обязан бросить её дальше:

defer func() {
    if r := recover(); r != nil {
        if _, ok := r.(myPanic); !ok {
            panic(r) // re-panic
        }
    }
}()

Re-panic продолжает разматывание, как будто recover не было.

Где recover действительно живёт

На границах, где паника не должна убить процесс. Классическое место — HTTP-сервер: стандартный net/http перехватывает панику на уровне соединения (в conn.serve), чтобы один упавший запрос не обрушил весь сервис. Или граница между чужим кодом и твоим, когда библиотека паникует, а тебе нужна ошибка.

recover не для управления потоком: превращать панику в механизм передачи ошибок между уровнями — медленно, неудобно и сбивает с толку. Паника — аварийный тормоз, а не ещё один способ вернуть ошибку.

В следующем уроке

Вы узнаете:

  • как net/http реализует перехват паники в обработчиках
  • чем os.Exit отличается от паники
Задание · вопросы

Проверьте себя

Вопрос 1 из 3

panic(nil) на Go 1.21+. Что возвращает recover?

Вопрос 2 из 3

Паника в HTTP-обработчике net/http. Что произойдёт с сервисом?

Вопрос 3 из 3

В defer поймана чужая паника, которую ты не обрабатываешь. Что делать?

Итоги

panic(nil) теперь отличим; чужую панику не глотают — бросают дальше. recover оправдан на границах, где падение одного запроса не должно рушить сервис.

Наш сайт собирает куки. Чтобы тебе было удобнее им пользоваться. Нажимая на кнопку, ты даёшь разрешение собирать куки