Menu
Coddy logo textTech

Обертывание ошибок с помощью `%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", создавая четкий след того, что и где произошло.

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

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

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

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

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

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

challenge icon

Задание

Легко

Создайте систему обработки файлов, которая оборачивает ошибки контекстной информацией по мере их распространения через различные уровни вашего приложения. Эта задача демонстрирует, как использовать глагол форматирования %w с fmt.Errorf для создания цепочек ошибок, которые сохраняют исходную ошибку, добавляя при этом значимый контекст.

Вы получите два входных значения:

  • Строку, содержащую детали операции с файлом в формате "filename,operation,status" (например, "config.json,read,permission_denied")
  • Строку, содержащую системный контекст в формате "service_name,component" (например, "UserService,ConfigLoader")

Ваша задача:

  1. Разобрать первый входной параметр, разделив его по запятым, чтобы получить имя файла (filename), операцию (operation) и статус (status)
  2. Разобрать второй входной параметр, разделив его по запятым, чтобы получить имя сервиса (service name) и компонент (component)
  3. Создать исходную ошибку на основе статуса, используя errors.New():
    • Если статус "permission_denied": "permission denied"
    • Если статус "not_found": "file not found"
    • Если статус "corrupted": "file corrupted"
    • Для любого другого статуса: "unknown error"
  4. Создать обернутую ошибку уровня файла, используя fmt.Errorf с %w: "failed to [operation] file [filename]: %w"
  5. Создать обернутую ошибку уровня компонента: "[component] error: %w"
  6. Создать обернутую ошибку уровня сервиса: "[service_name] operation failed: %w"
  7. Отобразить цепочку ошибок, распечатав каждый уровень:
    • "Original error: [original_error_message]"
    • "File level: [file_level_error_message]"
    • "Component level: [component_level_error_message]"
    • "Service level: [service_level_error_message]"
  8. Отобразить сводку цепочки ошибок:
    • "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: Напишите свой код ниже
	// Создание исходной ошибки на основе статуса
	// Создание обернутой ошибки на уровне файла
	// Создание обернутой ошибки на уровне компонента
	// Создание обернутой ошибки на уровне сервиса
	// Вывод каждого уровня ошибки и сводки
	
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Логика и управление потоком