Ошибки как значения

В Go ошибки — это значения. Никаких исключений: проверяй err и решай, что делать.

error — встроенный интерфейс с единственным методом Error() string. Функции возвращают ошибку как обычное значение, а вызывающий явно её проверяет.

Ошибки как значения

В Go нет try/catch. Вместо этого функция, способная завершиться неудачей, возвращает дополнительное значение типа error. Если ошибки нет — оно nil. Это центральная идиома языка, и её видно повсюду.

package main

import (
    "fmt"
    "strconv"
)

func main() {
    n, err := strconv.Atoi("123")
    if err != nil {
        fmt.Println("ошибка:", err)
        return
    }
    fmt.Println("число:", n)
}

Вывод:

число: 123

Связка if err != nil { ... } — самая частая в Go-коде. Поначалу она кажется многословной, но делает поток ошибок видимым: вы не можете случайно «пропустить» ошибку, как необработанное исключение.

Создание ошибок

Свои ошибки создают двумя способами. errors.New — для простого текста. fmt.Errorf — когда нужно подставить детали в сообщение.

package main

import (
    "errors"
    "fmt"
)

func withdraw(balance, amount int) (int, error) {
    if amount <= 0 {
        return balance, errors.New("сумма должна быть положительной")
    }
    if amount > balance {
        return balance, fmt.Errorf("недостаточно средств: нужно %d, есть %d", amount, balance)
    }
    return balance - amount, nil
}

func main() {
    _, err := withdraw(100, 150)
    if err != nil {
        fmt.Println(err)
    }
    rest, err := withdraw(100, 30)
    if err == nil {
        fmt.Println("остаток:", rest)
    }
}

Вывод:

недостаточно средств: нужно 150, есть 100
остаток: 70

Оборачивание ошибок

Чтобы добавить контекст, не теряя исходную ошибку, используют %w в fmt.Errorf. Это «оборачивает» ошибку: позже её можно достать через errors.Is или errors.As. Так строится цепочка контекста — от низкоуровневой причины до верхнеуровневого описания.

if err != nil {
    return fmt.Errorf("загрузка конфига: %w", err)
}

Идиома раннего возврата

Go-код почти не использует глубокую вложенность. Ошибки обрабатывают сразу и выходят (return), а «счастливый путь» остаётся слева, без отступов. Это делает функции плоскими и читаемыми.

Итог

  • Ошибка — значение типа error; нет ошибки = nil. Исключений в Go нет.
  • Создание: errors.New для текста, fmt.Errorf с %w для контекста.
  • Идиома if err != nil + ранний возврат держит код плоским и явным.
Проверьте себя
1. Как Go сигнализирует об ошибке?
AБросает исключение
BВозвращает значение типа error (nil, если ошибки нет)
CЗаписывает в глобальный лог
DЗавершает программу
2. Чем удобен fmt.Errorf с глаголом %w?
AУскоряет программу
BОборачивает исходную ошибку, добавляя контекст и сохраняя её для errors.Is/As
CУдаляет ошибку
DПечатает ошибку в консоль
3. Что означает err == nil после вызова функции?
AФункция не выполнилась
BОшибки не произошло, результат корректен
CПроизошла критическая ошибка
DНужно повторить вызов
Поддержать проект