Обертывание ошибок с помощью `%w`
Часть раздела Логика и управление потоком путешествия по GO на Coddy — урок 39 из 68.
Когда в вашем приложении возникают ошибки, им часто требуется дополнительный контекст по мере того, как они передаются вверх через различные уровни вашего кода. Go предоставляет мощный механизм для этого посредством оборачивания ошибок с использованием глагола форматирования %w в fmt.Errorf.
Обертывание ошибок (error wrapping) позволяет добавлять контекстную информацию к существующей ошибке, сохраняя при этом исходную ошибку. Это создает цепочку ошибок, которая сохраняет полную историю того, что пошло не так:
originalErr := errors.New("file not found")
wrappedErr := fmt.Errorf("failed to load config: %w", originalErr)Спецификатор %w является особенным — он указывает fmt.Errorf обернуть ошибку, а не просто преобразовать её в строку. Это сохраняет исходную ошибку, чтобы её можно было изучить позже с помощью таких функций, как errors.Is и errors.As.
Этот паттерн особенно ценен в крупных приложениях, где ошибка может проходить через несколько функций, каждая из которых добавляет свой контекст. Например, ошибка подключения к базе данных может быть обернута сообщением "failed to connect to database", а затем снова обернута сообщением "unable to start server", создавая четкий след того, что и где произошло.
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Задание
ЛегкоСоздайте систему обработки файлов, которая оборачивает ошибки контекстной информацией по мере их распространения через различные уровни вашего приложения. Эта задача демонстрирует, как использовать глагол форматирования %w с fmt.Errorf для создания цепочек ошибок, которые сохраняют исходную ошибку, добавляя при этом значимый контекст.
Вы получите два входных значения:
- Строку, содержащую детали операции с файлом в формате
"filename,operation,status"(например,"config.json,read,permission_denied") - Строку, содержащую системный контекст в формате
"service_name,component"(например,"UserService,ConfigLoader")
Ваша задача:
- Разобрать первый входной параметр, разделив его по запятым, чтобы получить имя файла (filename), операцию (operation) и статус (status)
- Разобрать второй входной параметр, разделив его по запятым, чтобы получить имя сервиса (service name) и компонент (component)
- Создать исходную ошибку на основе статуса, используя
errors.New():- Если статус
"permission_denied":"permission denied" - Если статус
"not_found":"file not found" - Если статус
"corrupted":"file corrupted" - Для любого другого статуса:
"unknown error"
- Если статус
- Создать обернутую ошибку уровня файла, используя
fmt.Errorfс%w:"failed to [operation] file [filename]: %w" - Создать обернутую ошибку уровня компонента:
"[component] error: %w" - Создать обернутую ошибку уровня сервиса:
"[service_name] operation failed: %w" - Отобразить цепочку ошибок, распечатав каждый уровень:
"Original error: [original_error_message]""File level: [file_level_error_message]""Component level: [component_level_error_message]""Service level: [service_level_error_message]"
- Отобразить сводку цепочки ошибок:
"Error Chain Summary:""File: [filename]""Operation: [operation]""Component: [component]""Service: [service_name]""Root cause: [original_error_message]"
Используйте пакет strings для разделения входных строк по запятым, пакет errors для создания исходной ошибки и пакет fmt для создания обернутых ошибок. Эта задача демонстрирует, как оборачивание ошибок с помощью %w создает четкий след контекста по мере прохождения ошибок через различные уровни вашего приложения, что делает отладку гораздо более эффективной.
Шпаргалка
Обертывание ошибок позволяет добавлять контекстную информацию к существующей ошибке, сохраняя при этом исходную ошибку. Используйте спецификатор формата %w с функцией fmt.Errorf:
originalErr := errors.New("file not found")
wrappedErr := fmt.Errorf("failed to load config: %w", originalErr)Спецификатор %w сохраняет исходную ошибку, чтобы её можно было проверить позже с помощью таких функций, как errors.Is и errors.As. Это создает цепочку ошибок, которая сохраняет полную историю того, что пошло не так, что особенно ценно, когда ошибки проходят через несколько функций в крупных приложениях.
Попробуйте сами
package main
import (
"errors"
"fmt"
"strings"
)
func main() {
// Чтение входных данных
var fileDetails string
var systemContext string
fmt.Scanln(&fileDetails)
fmt.Scanln(&systemContext)
// Разбор входных данных
fileInfo := strings.Split(fileDetails, ",")
filename := fileInfo[0]
operation := fileInfo[1]
status := fileInfo[2]
contextInfo := strings.Split(systemContext, ",")
serviceName := contextInfo[0]
component := contextInfo[1]
// TODO: Напишите свой код ниже
// Создание исходной ошибки на основе статуса
// Создание обернутой ошибки на уровне файла
// Создание обернутой ошибки на уровне компонента
// Создание обернутой ошибки на уровне сервиса
// Вывод каждого уровня ошибки и сводки
}В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Логика и управление потоком
1Продвинутое управление потоком выполнения
Switch с использованием `fallthrough`Выход из вложенных цикловПродолжение конкретного циклаОператор `goto`Итоги: Продвинутое управление циклами4Проект: Простой список задач
Настройка проектаДобавление задачи7Углубленная обработка ошибок
Пользовательские типы ошибокОбертывание ошибок с помощью `%w`Распаковка с помощью `errors.Is`Распаковка с помощью `errors.As`Понимание `panic`Использование `recover`Итоги: Безопасное деление2Структуры и методы
Определение методов для структурПолучатели по значениюПолучатели по указателюВыбор типа получателяМетоды против функцийИтоги: поведение структур5Карты: подробный разбор
Карты структурУказатели как значения картПроверка карт на nilСравнение картИтоги: счетчик частоты слов3Интерфейсы (Основы)
Что такое интерфейс?Определение интерфейсаРеализация интерфейсаИспользование интерфейсных типовПустой интерфейсУтверждение типаПереключатель типовИтоги: Фигуры и поведение