Материал проходит вычитку — возможны неточности.
Урок 49 из 118

Оборачивание через %w

ErrNotFound прижился, но в логах отовсюду торчало голое «not found»: было непонятно, какой шаг потерял файл. Миша завернул ошибку в контекст так, чтобы причина не потерялась.

Главная мысль

%w в fmt.Errorf оборачивает ошибку, сохраняя цепочку причин; %v цепочку обрывает.

%w строит цепочку

func loadMeta(path string) error {
    data, err := os.ReadFile(path)
    if err != nil {
        return fmt.Errorf("не удалось прочитать файл: %w", err)
    }
    // ...
}

%w заворачивает исходную ошибку внутрь новой: новая ошибка — текст с контекстом, а внутри — причина. Уровни добавляют контекст, не теряя исходник: «не удалось прочитать файл: открыть report.pdf: файл не существует».

%v обрывает связь

return fmt.Errorf("не удалось прочитать файл: %v", err)

%v просто печатает текст ошибки внутрь новой. Получается строка, а не цепочка: исходную ошибку внутри уже не найти — errors.Is и errors.As (следующий урок) не увидят причину.

Зачем цепочка

if errors.Is(err, fs.ErrNotExist) {
    // файла нет — создаём дефолтную запись
}

Вызывающий различает причины сквозь всю глубину контекста: наверху он видит длинную цепочку, но по errors.Is понимает — где-то внизу fs.ErrNotExist, а значит, файла нет и можно завести дефолтную запись. Без цепочки пришлось бы сравнивать строки или тащить тип ошибки через все уровни.

В следующем уроке

Вы узнаете:

  • как errors.Join объединяет несколько причин
  • как написать собственный Unwrap() для типа ошибки
Задание · вопросы

Проверьте себя

Вопрос 1 из 3

Что делает %w в fmt.Errorf?

Вопрос 2 из 3

Что делает %v в fmt.Errorf?

Вопрос 3 из 3

Как errors.Is находит причину сквозь обёртки?

Итоги

%w — обернуть с сохранением причины; %v — просто напечатать текст. Цепочка — то, что позволяет верхнему уровню различать причины.

Наш сайт собирает куки. Чтобы тебе было удобнее им пользоваться. Нажимая на кнопку, ты даёшь разрешение собирать куки