Menu
Coddy logo textTech

Recapitulação - Divisão Segura

Parte da seção Lógica & Fluxo do Journey de GO da Coddy — lição 44 de 68.

challenge icon

Desafio

Fácil

Construa uma calculadora matemática abrangente que implemente a divisão segura com múltiplos tipos de erro personalizados e tratamento de erros adequado. Este desafio combina tipos de erro personalizados, empacotamento de erros (error wrapping) e verificação de erros para criar um sistema robusto que lida com várias falhas de operações matemáticas de forma elegante.

Você receberá duas entradas:

  • Uma string contendo detalhes da operação no formato "operation,num1,num2,precision" (ex: "divide,10,0,2")
  • Uma string contendo as configurações da calculadora no formato "calculator_name,mode" (ex: "ScientificCalc,strict")

Sua tarefa é:

  1. Criar dois tipos de erro personalizados:
    • Struct DivisionError com os campos Dividend (float64) e Divisor (float64)
    • Struct ValidationError com os campos Field (string) e Value (float64)
  2. Implementar o método Error() string para DivisionError que retorna: "division error: cannot divide [dividend] by [divisor]"
  3. Implementar o método Error() string para ValidationError que retorna: "validation error: invalid [field] value [value]"
  4. Analisar a primeira entrada dividindo-a por vírgulas para obter operation, num1, num2 e precision
  5. Analisar a segunda entrada dividindo-a por vírgulas para obter calculator name e mode
  6. Converter os números em string para float64 e precision para int
  7. Criar uma função safeDivide que recebe dois parâmetros float64 e retorna (float64, error):
    • Se o divisor for 0, retorne 0 e um DivisionError com os valores de dividendo e divisor
    • Se o dividendo for negativo e o modo for "strict", retorne 0 e um ValidationError com o campo "dividend" e o valor do dividendo
    • Se o divisor for negativo e o modo for "strict", retorne 0 e um ValidationError com o campo "divisor" e o valor do divisor
    • Caso contrário, retorne o resultado da divisão e nil
  8. Criar uma função performCalculation que empacota o resultado de safeDivide:
    • Se safeDivide retornar um erro, empacote-o com: "calculation failed in [calculator_name]: %w"
    • Se for bem-sucedido, retorne o resultado e nil
  9. Chamar performCalculation e tratar o resultado:
    • Se não houver erro: imprima "Calculation successful: [result_formatted_to_precision_decimal_places]"
    • Se houver erro: imprima "Calculation failed: [error_message]"
  10. Usar errors.As para verificar tipos de erro específicos no erro empacotado:
    • Imprima "Checking for division error: [true/false]"
    • Imprima "Checking for validation error: [true/false]"
  11. Se um DivisionError for encontrado, imprima seus detalhes:
    • "Division Error Details:"
    • "Dividend: [dividend]"
    • "Divisor: [divisor]"
  12. Se um ValidationError for encontrado, imprima seus detalhes:
    • "Validation Error Details:"
    • "Field: [field]"
    • "Value: [value]"
  13. Exibir um resumo final:
    • "Calculator Summary:"
    • "Name: [calculator_name]"
    • "Mode: [mode]"
    • "Operation: [operation]"
    • "Input: [num1] [operation_symbol] [num2]" onde operation_symbol é "/" para divisão
    • "Precision: [precision] decimal places"
    • "Status: [Success/Failed]"

Use o pacote strings para dividir as strings de entrada por vírgulas, o pacote strconv para converter strings em números, o pacote errors para errors.As e o pacote fmt para empacotamento e formatação de erros. Este desafio demonstra como tipos de erro personalizados, empacotamento de erros e a verificação adequada de erros trabalham juntos para criar sistemas robustos de tratamento de erros que fornecem informações detalhadas sobre diferentes tipos de falhas.

Experimente você mesmo

package main

import (
	"errors"
	"fmt"
	"strconv"
	"strings"
)

func main() {
	// Ler entrada
	var operationInput string
	var settingsInput string
	fmt.Scanln(&operationInput)
	fmt.Scanln(&settingsInput)
	
	// Analisar entrada da operação (operação,num1,num2,precisão)
	operationParts := strings.Split(operationInput, ",")
	operation := operationParts[0]
	num1, _ := strconv.ParseFloat(operationParts[1], 64)
	num2, _ := strconv.ParseFloat(operationParts[2], 64)
	precision, _ := strconv.Atoi(operationParts[3])
	
	// Analisar entrada de configurações (nome_da_calculadora,modo)
	settingsParts := strings.Split(settingsInput, ",")
	calculatorName := settingsParts[0]
	mode := settingsParts[1]
	
	// TODO: Escreva seu código abaixo
	// 1. Criar as structs DivisionError e ValidationError com métodos Error()
	// 2. Implementar a função safeDivide
	// 3. Implementar a função performCalculation
	// 4. Chamar performCalculation e tratar os resultados
	// 5. Usar errors.As para verificar tipos de erro específicos
	// 6. Imprimir detalhes do erro se encontrado
	// 7. Exibir resumo final
	
}

Todas as lições de Lógica & Fluxo