Как в Go обрабатываются ошибки? Есть ли в языке исключения (exceptions)?

Ответ

В Go отсутствует классический механизм исключений (try-catch), принятый в таких языках, как Java или C++. Вместо этого в Go используется идиоматический подход явной обработки ошибок.

Основной механизм — возврат значения типа error

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

  • Тип error — это встроенный интерфейс.
  • Если ошибки нет, функция возвращает nil.

Пример:

import (
    "fmt"
    "log"
)

func divide(a, b int) (int, error) {
    if b == 0 {
        // Создаем новую ошибку
        return 0, fmt.Errorf("деление на ноль запрещено")
    }
    return a / b, nil // Ошибки нет, возвращаем nil
}

func main() {
    result, err := divide(10, 0)
    if err != nil {
        // Обрабатываем ошибку
        log.Printf("Произошла ошибка: %v", err)
        return
    }
    fmt.Println("Результат:", result)
}

Механизм panic и recover

Для действительно исключительных, нештатных ситуаций в Go существуют встроенные функции panic() и recover().

  • panic(): Прерывает обычный поток выполнения программы и начинает "паниковать". Выполнение функции останавливается, а все отложенные вызовы (defer) выполняются в обратном порядке.
  • recover(): Позволяет перехватить panic и восстановить нормальное выполнение. recover имеет смысл вызывать только внутри defer.

Важно: panic/recover не предназначены для обычной обработки ошибок (например, "файл не найден"). Их следует использовать только для критических, непредвиденных ситуаций, после которых программа не может продолжать адекватную работу (например, обращение по nil-указателю, выход за пределы слайса).