Итоги — безопасное деление
Часть раздела Логика и управление потоком путешествия по GO на Coddy. Урок 44 из 68.
Задание
ЛегкоСоздайте полноценный математический калькулятор, который выполняет безопасное деление с несколькими пользовательскими типами ошибок и корректной обработкой ошибок. Это задание объединяет пользовательские типы ошибок, оборачивание ошибок и проверку ошибок для создания надежной системы, которая корректно обрабатывает различные сбои математических операций.
Вы получите два входных значения:
- Строку со сведениями об операции в формате
"operation,num1,num2,precision"(например,"divide,10,0,2") - Строку с настройками калькулятора в формате
"calculator_name,mode"(например,"ScientificCalc,strict")
Ваша задача:
- Создать два пользовательских типа ошибок:
- структуру
DivisionErrorс полямиDividend(float64) иDivisor(float64) - структуру
ValidationErrorс полямиField(string) иValue(float64)
- структуру
- Реализовать метод
Error() stringдляDivisionError, который возвращает:"division error: cannot divide [dividend] by [divisor]" - Реализовать метод
Error() stringдляValidationError, который возвращает:"validation error: invalid [field] value [value]" - Разобрать первую строку, разделив её по запятым, чтобы получить операцию, num1, num2 и precision
- Разобрать вторую строку, разделив её по запятым, чтобы получить название калькулятора и режим
- Преобразовать числовые строки в float64, а precision — в int
- Создать функцию
safeDivide, принимающую два параметра типа float64 и возвращающую (float64, error):- Если делитель равен 0, вернуть 0 и
DivisionErrorсо значениями делимого и делителя - Если делимое отрицательное, а режим —
"strict", вернуть 0 иValidationErrorс полем"dividend"и значением делимого - Если делитель отрицательный, а режим —
"strict", вернуть 0 иValidationErrorс полем"divisor"и значением делителя - В противном случае вернуть результат деления и nil
- Если делитель равен 0, вернуть 0 и
- Создать функцию
performCalculation, которая оборачивает результатsafeDivide:- Если
safeDivideвозвращает ошибку, обернуть её так:"calculation failed in [calculator_name]: %w" - При успешном выполнении вернуть результат и nil
- Если
- Вызвать
performCalculationи обработать результат:- Если ошибки нет: вывести
"Calculation successful: [result_formatted_to_precision_decimal_places]" - Если возникла ошибка: вывести
"Calculation failed: [error_message]"
- Если ошибки нет: вывести
- Использовать
errors.As, чтобы проверить наличие определённых типов ошибок в обёрнутой ошибке:- Вывести
"Checking for division error: [true/false]" - Вывести
"Checking for validation error: [true/false]"
- Вывести
- Если найдена ошибка
DivisionError, вывести её сведения:"Division Error Details:""Dividend: [dividend]""Divisor: [divisor]"
- Если найдена ошибка
ValidationError, вывести её сведения:"Validation Error Details:""Field: [field]""Value: [value]"
- Вывести итоговую сводку:
"Calculator Summary:""Name: [calculator_name]""Mode: [mode]""Operation: [operation]""Input: [num1] [operation_symbol] [num2]", где operation_symbol — это "/" для деления"Precision: [precision] decimal places""Status: [Success/Failed]"
Используйте пакет strings, чтобы разделить входные строки по запятым, пакет strconv для преобразования строк в числа, пакет errors для errors.As, а пакет fmt для оборачивания ошибок и форматирования. Это задание показывает, как пользовательские типы ошибок, оборачивание ошибок и корректная проверка ошибок работают вместе, обеспечивая надёжную обработку ошибок с подробной информацией о различных типах сбоев.
Попробуйте сами
package main
import (
"errors"
"fmt"
"strconv"
"strings"
)
func main() {
// Считайте входные данные
var operationInput string
var settingsInput string
fmt.Scanln(&operationInput)
fmt.Scanln(&settingsInput)
// Разберите входные данные операции (operation,num1,num2,precision)
operationParts := strings.Split(operationInput, ",")
operation := operationParts[0]
num1, _ := strconv.ParseFloat(operationParts[1], 64)
num2, _ := strconv.ParseFloat(operationParts[2], 64)
precision, _ := strconv.Atoi(operationParts[3])
// Разберите входные данные настроек (calculator_name,mode)
settingsParts := strings.Split(settingsInput, ",")
calculatorName := settingsParts[0]
mode := settingsParts[1]
// TODO: Напишите свой код ниже
// 1. Создайте структуры DivisionError и ValidationError с методами Error()
// 2. Реализуйте функцию safeDivide
// 3. Реализуйте функцию performCalculation
// 4. Вызовите performCalculation и обработайте результаты
// 5. Используйте errors.As для проверки конкретных типов ошибок
// 6. Выведите сведения об ошибках, если они обнаружены
// 7. Выведите итоговую сводку
}Все уроки раздела Логика и управление потоком
1Продвинутое управление потоком
Оператор switch с `fallthrough`Выход из вложенных цикловПереход к следующей итерации конкретного циклаОператор `goto`Повторение: расширенное управление циклами4Проект: простой список задач
Настройка проектаДобавление задачи7Обработка ошибок: углублённый разбор
Пользовательские типы ошибокОбёртывание ошибок с помощью `%w`Извлечение исходной ошибки с помощью `errors.Is`Извлечение исходной ошибки с помощью `errors.As`Разбираемся с `panic`Использование `recover`Итоги — безопасное деление2Структуры и методы
Определение методов для структурПолучатели-значенияПолучатели-указателиВыбор получателейМетоды и функцииПовторение: поведение структур5Карты: подробный разбор
Карты структурУказатели как значения картПроверка карт на nilСравнение картПовторение — счётчик частоты слов8Проект: простой складской учёт
Обзор проектаПроверка запасов3Интерфейсы (основы)
Что такое интерфейс?Определение интерфейсаРеализация интерфейсаИспользование типов интерфейсовПустой интерфейсУтверждения типовПереключатель типовПовторение — формы и поведениеПотренируйтесь самостоятельно: Онлайн-компилятор Go