РЕПЕТИТОР математика физика информатика
Для школьников и студентов. Подтягивание пробелов. ЦЭ, ЦТ, ОГЭ, ЕГЭ.
Идет набор на ЛЕТО. Жмите для подробностей:)
497 of 1593 menu

Panic vs error

В Go существуют два основных механизма для обработки ошибок и исключительных ситуаций: error и panic. error — это значение, которое функция возвращает для информирования о нормальной (ожидаемой) ошибке, которую вызывающий код должен обработать. panic — это необработанная ошибка времени выполнения, которая останавливает нормальный поток выполнения и начинает раскрутку стека.

Основное отличие в том, что error является частью контракта функции и предполагает, что вызывающий код может и должен ее обработать, тогда как panic сигнализирует о критической ситуации, из которой невозможно восстановиться штатными средствами, например, о внутренней ошибке программы.

Использование error

error — это встроенный интерфейс, который используется для возврата ошибок из функций. Это основной способ сообщить об ошибке в Go. Функция возвращает ошибку, и вызывающий код проверяет, равна ли она nil, чтобы определить, произошла ли ошибка.

package main import ( "errors" "fmt" ) func divide(a, b int) (int, error) { if b == 0 { return 0, errors.New("division by zero") } return a / b, nil } func main() { res, err := divide(10, 0) if err != nil { fmt.Println("Error:", err) return } fmt.Println("Result:", res) }

Результат выполнения кода:

"Error: division by zero"

Использование panic

panic используется в ситуациях, когда программа не может или не должна продолжать выполнение. Например, при обнаружении внутренней логической ошибки, которая свидетельствует о баге в коде. Вызов panic приводит к немедленной остановке выполнения текущей функции и раскрутке стека горутины.

package main import "fmt" func mustDivide(a, b int) int { if b == 0 { panic("division by zero is not allowed") } return a / b } func main() { res := mustDivide(10, 0) fmt.Println("Result:", res) }

Результат выполнения кода (программа завершится с паникой):

"panic: division by zero is not allowed"

Когда использовать error

error следует использовать для ожидаемых ошибок, которые являются частью нормальной работы программы. Например, ошибка открытия файла, ошибка парсинга данных, ошибка валидации ввода. Такие ошибки должны быть явно обработаны вызывающим кодом.

package main import ( "fmt" "os" ) func readFile(filename string) ([]byte, error) { data, err := os.ReadFile(filename) if err != nil { return nil, fmt.Errorf("failed to read file: %w", err) } return data, nil } func main() { data, err := readFile("nonexistent.txt") if err != nil { fmt.Println("Error:", err) return } fmt.Println("File content:", string(data)) }

Результат выполнения кода:

"Error: failed to read file: open nonexistent.txt: no such file or directory"

Когда использовать panic

panic следует использовать для невосстановимых ошибок, которые не должны происходить в правильно работающей программе. Например, попытка доступа к элементу слайса за пределами его длины, или ситуация, когда программа находится в некорректном состоянии, из которого невозможно восстановиться.

package main import "fmt" func getElement(s []int, index int) int { if index < 0 || index >= len(s) { panic("index out of bounds") } return s[index] } func main() { slice := []int{1, 2, 3} res := getElement(slice, 5) fmt.Println("Element:", res) }

Результат выполнения кода (программа завершится с паникой):

"panic: index out of bounds"

Восстановление после panic

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

package main import "fmt" func safeDivide(a, b int) (result int, err error) { defer func() { if r := recover(); r != nil { err = fmt.Errorf("recovered from panic: %v", r) } }() if b == 0 { panic("division by zero") } return a / b, nil } func main() { res, err := safeDivide(10, 0) if err != nil { fmt.Println("Error:", err) } else { fmt.Println("Result:", res) } }

Результат выполнения кода:

"Error: recovered from panic: division by zero"

Советы по выбору

При разработке на Go старайтесь придерживаться принципа: используйте error для всего, что может пойти не так в нормальной работе программы. Используйте panic только для действительно исключительных ситуаций, которые свидетельствуют о багах или невосстановимых ошибках. Хорошая практика — покрывать panic в точках входа в программу (например, в main) для логирования и graceful shutdown.

Смотрите также

  • интерфейс error,
    который является основой для обработки ошибок в Go
  • функцию errors.New,
    которая создает простую ошибку с текстовым сообщением
  • обертывание ошибок через wrapping,
    которое позволяет добавлять контекст к ошибкам
  • обработку ошибок через checking,
    которая описывает стандартные паттерны проверки ошибок
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить