Перейти к основному содержимому

Практика: Обработка ошибок и паники


Онлайн редактор кода для Go

Здесь вы можете попробовать свои силы в программировании на языке Go. Для этого мы предоставляем вам онлайн редактор кода, в котором вы можете написать свой код и запустить его.


❗️ При обновлении страницы код пропадёт, по этому, сохраните свой код куда-нибудь, если он важный.

Задание 1 — Безопасный делитель с контекстом

Задание 1: Безопасный делитель

⏱️ Примерное время: 10-15 минут

Функция SafeDivide(a, b float64) (float64, error). Если b == 0 — верни ошибку с контекстом через fmt.Errorf.


Требования:

  • если b == 0 — return 0, fmt.Errorf("деление %.2f на ноль недопустимо", a)
  • в main: если err != nil — выведи ошибку красным (или с эмодзи ⚠️)
  • если всё ок — результат с двумя знаками после запятой

Пример вывода:

10.0 / 2.0 = 5.00 ✅
15.5 / 0.0 → ⚠️ деление 15.50 на ноль недопустимо

Задание 2 — Валидация возраста с кастомной ошибкой

Задание 2: Валидация возраста

⏱️ Примерное время: 15-20 минут

Создай тип AgeError struct { Age int; Message string }. Реализуй Error(). Функция CheckAge(age int) error.


Требования:

  • структура AgeError { Age int; Message string }
  • метод Error() string → fmt.Sprintf("возраст %d: %s", e.Age, e.Message)
  • проверки: < 0, > 150
  • в main: type assertion if ae, ok := err.(AgeError); ok { … }

Пример вывода:

Возраст 25: всё в порядке ✓
Возраст -5: возраст не может быть отрицательным ✗

Задание 3 — Множественная валидация (errors.Join)

Задание 3: Множественная валидация пользователя

⏱️ Примерное время: 20-25 минут

Функция ValidateUser(name, email string, age int) error. Собери все ошибки через errors.Join.


Требования:

  • проверки: имя не пустое и не только пробелы, email содержит @, возраст 0–150
  • собирай ошибки в слайс []error, затем return errors.Join(errs...)
  • в main: если err != nil — выведи каждую ошибку отдельной строкой

Пример вывода:

Ошибки валидации:
имя обязательно
некорректный email
возраст должен быть от 0 до 150

Задание 4 — Паника при критической ошибке

Задание 4: Аварийная остановка ракеты

⏱️ Примерное время: 15-20 минут

Функция LaunchRocket(fuel int). Если топлива < 100 — паника. В main перехвати панику через defer + recover.


Требования:

  • if fuel < 100 { panic("недостаточно топлива") }
  • в main: defer func() { if r := recover(); r != nil { fmt.Printf("Авария! %v\nЭкипаж в безопасности", r) } }()
  • после recover можно продолжить работу (например, "миссия отменена")

Пример вывода:

Запускаем ракету...
Авария! недостаточно топлива
Экипаж в безопасности
Миссия отменена

Задание 5 — Логгер ошибок с slog

Задание 5: Логгер ошибок с slog

⏱️ Примерное время: 15-20 минут

Создай глобальный slog-логгер. Пиши в него ошибки с уровнем Error и атрибутами (operation, err).


Требования:

  • slog.SetDefault(slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo})))
  • функция LogError(msg string, err error, attrs ...any)
  • используй slog.Error(msg, "err", err, attrs...)
  • в main симулируй 3–5 ошибок

Пример вывода:

time=... level=ERROR msg="не удалось открыть файл" err="open config.json: no such file" operation=load_config

Задание 6 — Chain of errors (обёртывание)

Задание 6: Цепочка ошибок

⏱️ Примерное время: 25-35 минут

Функции: ReadFile → ParseConfig → ValidateConfig. Каждая оборачивает ошибку через %w. В main проверяй errors.Is и errors.As.


Требования:

  • ReadFile(path) ([]byte, error)fmt.Errorf("не удалось прочитать %s: %w", path, err)
  • ParseConfig(data []byte) (Config, error)%w
  • ValidateConfig(cfg Config) error → кастомная ошибка или fmt.Errorf
  • в main: errors.Is(err, os.ErrNotExist), errors.As(err, &target)

Пример вывода:

Ошибка: не удалось прочитать config.json: open config.json: no such file or directory
Файл точно не найден

Задание 7 — Итоговое: Надёжный загрузчик конфига

Задание 7: Надёжный загрузчик конфига (итоговое)

⏱️ Примерное время: 35-50 минут

Программа загружает config.json. Обрабатывай все возможные ошибки: файл не найден, неверный JSON, невалидные значения. Логируй через slog.


Требования:

  • структура Config { Name string; Age int; Email string }
  • функция LoadConfig(path string) (Config, error)
  • используй errors.Is, errors.As, errors.Join
  • логируй через slog.Error с атрибутами
  • если файл не найден — верни дефолтный конфиг и залогируй Warn

Пример вывода:

WARN Конфиг не найден — использую значения по умолчанию
Загружен конфиг: {Artem 28 artem@example.com}
подсказка

Ошибки — это не враги, а друзья.
Проверяй их явно, оборачивай для контекста, логируй через slog — и твой код будет надёжным и понятным.