ПрограммированиеBackend разработчик

Приведите подробное сравнение panic/recover и стандартного error handling в Go: отличия, лучшие практики, подводные камни. Когда оправдано использовать panic?

Проходите собеседования с ИИ помощником Hintsage

Ответ.

В Go стандартный подход — обработка ошибок через возвращаемое значение error. Это позволяет явно контролировать, что делать при возникновении ошибки в каждой точке. Panic — механизм для обработки непредвиденных катастрофических ситуаций: она прерывает выполнение до ближайшего defer, где можно использовать recover для "спасения". Но recover работает только внутри defer.

Лучшие практики:

  • Использовать error для обычных ситуаций и ожидаемых ошибок (файл не найден, запрос невалиден).
  • Panic — только для критических сбоев, когда продолжение работы невозможно (например, нарушение инвариантов, ошибка в инициализации).
  • Никогда не использовать panic для обычного flow (например, для валидации данных).
func safeDivide(a, b int) (int, error) { if b == 0 { return 0, errors.New("divide by zero") } return a/b, nil } func mustDivide(a, b int) int { if b == 0 { panic("divide by zero!") } return a/b }

Вопрос с подвохом.

Можно ли "поймать" любую паник ошибку с помощью recover в любом месте программы?

Ответ: Нет, recover сработает только внутри defer и только в той же горутине, где вызвана паника. В других случаях паника завершит выполнение этой (или всех) горутин — это часто становится неожиданностью.

Примеры реальных ошибок из-за незнания тонкостей темы.


История

В REST API использовали panic для обработки обычных ошибок в бизнес-логике. Это привело к неочевидным падениям приложения и некорректным логам, потому что recover корректно срабатывал не всегда.


История

В сервисе обработки платежей был реализован defer + recover в основной функции, чтобы "ловить" все паники, но забыли про горутины — в дочерних горутинах без defer/recover приложение падало с "страшными" ошибками, оставляя часть транзакций в неконсистентном состоянии.


История

В парсере сложных структур забыли сделать возврат ошибки, заменили его на panic — это усложнило сопровождение и тестирование, пришлось полностью переписывать обработку ошибок, чтобы иметь детальное логирование и корректный UX.