Menu
Coddy logo textTech

Итоги: Безопасное деление

Часть раздела Логика и управление потоком путешествия по GO на Coddy — урок 44 из 68.

challenge icon

Задание

Легко

Создайте комплексный математический калькулятор, который реализует безопасное деление с использованием нескольких пользовательских типов ошибок и правильной обработкой ошибок. Эта задача объединяет пользовательские типы ошибок, оборачивание ошибок (error wrapping) и проверку ошибок для создания надежной системы, которая корректно обрабатывает различные сбои математических операций.

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

  • Строка, содержащая детали операции в формате "operation,num1,num2,precision" (например, "divide,10,0,2")
  • Строка, содержащая настройки калькулятора в формате "calculator_name,mode" (например, "ScientificCalc,strict")

Ваша задача:

  1. Создать два пользовательских типа ошибок:
    • Структура DivisionError с полями Dividend (float64) и Divisor (float64)
    • Структура ValidationError с полями Field (string) и Value (float64)
  2. Реализовать метод Error() string для DivisionError, который возвращает: "division error: cannot divide [dividend] by [divisor]"
  3. Реализовать метод Error() string для ValidationError, который возвращает: "validation error: invalid [field] value [value]"
  4. Разобрать первый входной параметр, разделив его по запятым, чтобы получить operation, num1, num2 и precision
  5. Разобрать второй входной параметр, разделив его по запятым, чтобы получить calculator name и mode
  6. Преобразовать строковые числа в float64, а precision — в int
  7. Создать функцию safeDivide, которая принимает два параметра float64 и возвращает (float64, error):
    • Если делитель равен 0, вернуть 0 и DivisionError со значениями dividend и divisor
    • Если делимое отрицательное и mode равен "strict", вернуть 0 и ValidationError с полем "dividend" и значением dividend
    • Если делитель отрицательный и mode равен "strict", вернуть 0 и ValidationError с полем "divisor" и значением divisor
    • В противном случае вернуть результат деления и nil
  8. Создать функцию performCalculation, которая оборачивает результат safeDivide:
    • Если safeDivide возвращает ошибку, обернуть ее строкой: "calculation failed in [calculator_name]: %w"
    • В случае успеха вернуть результат и nil
  9. Вызвать performCalculation и обработать результат:
    • Если ошибки нет: вывести "Calculation successful: [result_formatted_to_precision_decimal_places]"
    • Если ошибка есть: вывести "Calculation failed: [error_message]"
  10. Использовать errors.As для проверки конкретных типов ошибок в обернутой ошибке:
    • Вывести "Checking for division error: [true/false]"
    • Вывести "Checking for validation error: [true/false]"
  11. Если обнаружена ошибка DivisionError, вывести ее детали:
    • "Division Error Details:"
    • "Dividend: [dividend]"
    • "Divisor: [divisor]"
  12. Если обнаружена ошибка ValidationError, вывести ее детали:
    • "Validation Error Details:"
    • "Field: [field]"
    • "Value: [value]"
  13. Отобразить итоговую сводку:
    • "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. Отобразите итоговую сводку
	
}

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