Ответ
В Go существует четкое разделение между ожидаемыми ошибками (error
) и критическими сбоями (panic
).
Error
- Это ожидаемое, предсказуемое состояние ошибки. Например, файл не найден, сетевое соединение прервано, неверный ввод пользователя.
- В Go идиоматично возвращать ошибки как последнее значение из функции:
val, err := someFunc()
. - Обработка
error
— это часть нормального потока выполнения программы. Вы должны проверятьif err != nil
и принимать решение, что делать дальше.
Panic
- Это непредвиденная, критическая ошибка времени выполнения, которая делает дальнейшее выполнение программы невозможным или бессмысленным. Например, обращение по nil-указателю, выход за пределы массива.
panic
останавливает выполнение текущей функции, запускает выполнение всех отложенных вызовов (defer
) в обратном порядке, а затем "всплывает" вверх по стеку вызовов, проделывая то же самое в вызывающих функциях. Еслиpanic
не будет обработана, программа аварийно завершится.
Обработка panic
с помощью recover
panic
можно перехватить и "обезвредить" с помощью встроенной функции recover
. Это позволяет программе продолжить выполнение.
Правила использования recover
:
recover
работает только внутри отложенной функции (defer
). Вызовrecover
в любом другом месте вернетnil
и не будет иметь эффекта.- Она перехватывает значение, переданное в
panic
, и позволяет его проанализировать.
Пример:
package main
import "fmt"
func safeDivision(a, b int) int {
// defer выполняется перед выходом из функции, в том числе при панике
defer func() {
// recover() перехватывает панику
if r := recover(); r != nil {
fmt.Printf("Recovered from panic: %vn", r)
// Здесь можно логировать ошибку или выполнять очистку
}
}()
fmt.Println("Calculating...")
// Эта строка вызовет панику, если b равно 0
result := a / b
return result
}
func main() {
safeDivision(10, 0)
fmt.Println("Program continues to run after panic was recovered.")
}
Ключевой вывод: Используйте error
для всех ожидаемых ошибок. Используйте panic
только для действительно исключительных ситуаций. Перехват panic
— это редкая практика, обычно применяемая на верхнем уровне приложения (например, в HTTP-сервере), чтобы предотвратить падение всего сервиса из-за ошибки в одном из обработчиков.