Ответ вслух Senior Ошибки, defer, panic и recover обновлено

Как работают panic, defer и recover

Вопрос

Расскажите, как устроены defer, panic и recover, где и зачем вы используете recover, и что нельзя перехватить.

Попробуйте сами

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

Показать ответ и разбор

Коротко

defer регистрирует вызов, аргументы которого вычислены сразу, а выполняется он при выходе из функции в обратном порядке.

Что должно прозвучать в ответе

  • defer кладёт вызов в список горутины, аргументы вычисляются сразу; выполняются LIFO при выходе

  • С Go 1.14 open-coded defer: почти бесплатный для простых случаев

  • panic разматывает стек текущей горутины, выполняя defer

  • recover работает только напрямую в отложенной функции той же горутины

  • Не перехватываются fatal error: concurrent map writes, нехватка памяти, deadlock

  • Использование: middleware сервера, обёртка воркеров, превращение паники в ошибку на границе библиотеки

Что могут спросить следом

  • Что будет, если паника случится внутри defer во время другой паники?
  • Почему не стоит использовать panic как исключение для обычных ошибок?

Разбор

defer регистрирует вызов, аргументы которого вычислены сразу, а выполняется он при выходе из функции в обратном порядке. С Go 1.14 простые defer без циклов компилятор встраивает прямо в код выхода (open-coded defer), поэтому их стоимость почти нулевая, и бояться defer в горячем коде больше не нужно. panic останавливает обычное выполнение и разматывает стек текущей горутины, выполняя отложенные функции. Если одна из них вызвала recover напрямую, паника останавливается, и функция с этим defer возвращается нормально, с теми именованными результатами, которые выставил defer. Если никто не перехватил, печатается паника со стеком и процесс завершается с кодом 2. Новая паника в defer во время паники заменяет текущую, а в выводе видны обе. recover использую на границах: middleware HTTP, обёртка горутин-воркеров, публичный API библиотеки, где паника внутри превращается в error. Нельзя перехватить fatal error рантайма: конкурентная запись в мапу, исчерпание памяти, deadlock всех горутин, переполнение стека. Для обычных ошибок panic не использую: это дорого, ломает явный поток управления и легко забыть recover в новой горутине.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.

Термины по теме