14 вопросов
type error interface { Error() string }. Любой тип с методом Error() string реализует error. Ошибки возвращают последним значением: func F() (int, error). Проверка: if err != nil { ... }. Стандартный способ обработки - явная проверка, без исключений.
С Go 1.13: fmt.Errorf("context: %w", err) - глагол %w оборачивает err. Оригинальная ошибка сохраняется и доступна через errors.Unwrap, errors.Is, errors.As. Цепочка обёрток позволяет добавлять контекст и проверять тип/значение вверх по цепочке.
error - ожидаемые сбои (сеть, ввод, файл не найден). Вызывающий решает, что делать. panic - невосстановимые ошибки программиста (nil pointer, нарушение инварианта) или когда продолжать невозможно. В библиотеках предпочтительно возвращать error. В main/init иногда panic допустим.
Пакет golang.org/x/sync/errgroup: группа горутин с общей обработкой ошибки. При первой ошибке в одной из горутин контекст отменяется, Wait возвращает эту ошибку. Удобно для параллельных задач с единой точкой выхода по ошибке. Group создаётся с контекстом, Go запускает горутины, Wait ждёт и возвращает ошибку.
Предопределённые ошибки для сравнения: var ErrNotFound = errors.New("not found"). Проверка: if err == ErrNotFound или if errors.Is(err, ErrNotFound). Подходят для известных состояний (io.EOF, sql.ErrNoRows). Не оборачивают без %w, иначе errors.Is не найдёт.
Один метод: Error() string. Возвращает строковое представление ошибки. Тип реализует error, если у него есть этот метод. В стандартной библиотеке часто используют errors.New и fmt.Errorf, возвращающие частные типы с методом Error().
Передать ошибку наружу: канал chan error, общая переменная под мьютексом, или errgroup. errgroup: запускать горутины через group.Go(), в конце group.Wait() возвращает первую ошибку. Нельзя использовать только возврат из горутины - его никто не получит.
Игнорирование: f(); g() без проверки err от f. Сравнение обёрнутой ошибки через == вместо errors.Is. Не оборачивать при добавлении контекста (теряется цепочка). Проверять err != nil до использования других возвращаемых значений. Не возвращать nil error после паники (recover).
errors.Is(err, target) проверяет, есть ли в цепочке err (через Unwrap) ошибка, равная target. Для sentinel: errors.Is(err, ErrNotFound). errors.As(err, &target) находит в цепочке первую ошибку, присваиваемую в тип target (указатель на тип/интерфейс), и записывает в target. Для проверки типа обёрнутой ошибки.
errors.New(s) создаёт ошибку с текстом s (приватный тип в пакете errors). fmt.Errorf(format, ...) форматирует сообщение; с глаголом %w оборачивает переданную ошибку (Go 1.13+). Для оборачивания используют fmt.Errorf с %w; для простой строки - errors.New.
Структура с методом Error() string. Для оборачивания и errors.Is/As реализовать Unwrap() error, возвращающий вложенную ошибку. Пример: type MyErr struct{ Err error }; func (e MyErr) Error() string { return e.Err.Error() }; func (e MyErr) Unwrap() error { return e.Err }. Проверка через errors.As.
errors.Join(err1, err2, ...) объединяет несколько ошибок в одну. Возвращаемая ошибка при вызове Error() возвращает объединённый текст. errors.Unwrap возвращает nil; для разбора используют цикл с errors.Unwrap для multi-error типов или проверяют через errors.Is по каждой.
Философия языка: явная обработка ошибок через возвращаемые значения. Код с ошибками виден (if err != nil), контроль потока предсказуем. Исключения скрывают ошибки и усложняют стек. В Go ошибка - часть контракта функции, вызывающий обязан её обработать или явно передать выше.
Обычно возвращают одну ошибку. Несколько: обёртка с цепочкой (Unwrap возвращает следующую), либо тип-коллектор (слайс ошибок), либо errors.Join (Go 1.20+). В API часто одна главная ошибка, остальные оборачиваются или логируются. errgroup собирает одну ошибку из группы горутин.