Recapitulação - Divisão Segura
Parte da seção Lógica & Fluxo do Journey de GO da Coddy. Lição 44 de 68.
Desafio
FácilCrie uma calculadora matemática abrangente que implemente divisão segura com vários tipos de erro personalizados e tratamento adequado de erros. Este desafio combina tipos de erro personalizados, encapsulamento de erros e verificação de erros para criar um sistema robusto que lida normalmente com várias falhas de operações matemáticas.
Você receberá duas entradas:
- Uma string contendo detalhes da operação no formato
"operation,num1,num2,precision"(por exemplo,"divide,10,0,2") - Uma string contendo as configurações da calculadora no formato
"calculator_name,mode"(por exemplo,"ScientificCalc,strict")
Sua tarefa é:
- Criar dois tipos de erro personalizados:
- Uma struct
DivisionErrorcom os camposDividend(float64) eDivisor(float64) - Uma struct
ValidationErrorcom os camposField(string) eValue(float64)
- Uma struct
- Implementar o método
Error() stringparaDivisionError, que retorna:"division error: cannot divide [dividend] by [divisor]" - Implementar o método
Error() stringparaValidationError, que retorna:"validation error: invalid [field] value [value]" - Analisar a primeira entrada dividindo-a pelas vírgulas para obter operation, num1, num2 e precision
- Analisar a segunda entrada dividindo-a pelas vírgulas para obter o nome e o modo da calculadora
- Converter os números em string para float64 e precision para int
- Criar uma função
safeDivideque receba dois parâmetros float64 e retorne (float64, error):- Se o divisor for 0, retornar 0 e um
DivisionErrorcom os valores de dividendo e divisor - Se o dividendo for negativo e o modo for
"strict", retornar 0 e umValidationErrorcom o campo"dividend"e o valor do dividendo - Se o divisor for negativo e o modo for
"strict", retornar 0 e umValidationErrorcom o campo"divisor"e o valor do divisor - Caso contrário, retornar o resultado da divisão e nil
- Se o divisor for 0, retornar 0 e um
- Criar uma função
performCalculationque encapsule o resultado desafeDivide:- Se
safeDivideretornar um erro, encapsulá-lo com:"calculation failed in [calculator_name]: %w" - Se for bem-sucedida, retornar o resultado e nil
- Se
- Chamar
performCalculatione tratar o resultado:- Se não houver erro: imprimir
"Calculation successful: [result_formatted_to_precision_decimal_places]" - Se existir um erro: imprimir
"Calculation failed: [error_message]"
- Se não houver erro: imprimir
- Usar
errors.Aspara verificar tipos de erro específicos no erro encapsulado:- Imprimir
"Checking for division error: [true/false]" - Imprimir
"Checking for validation error: [true/false]"
- Imprimir
- Se um
DivisionErrorfor encontrado, imprimir seus detalhes:"Division Error Details:""Dividend: [dividend]""Divisor: [divisor]"
- Se um
ValidationErrorfor encontrado, imprimir seus detalhes:"Validation Error Details:""Field: [field]""Value: [value]"
- Exibir um resumo final:
"Calculator Summary:""Name: [calculator_name]""Mode: [mode]""Operation: [operation]""Input: [num1] [operation_symbol] [num2]", em que operation_symbol é "/" para divisão"Precision: [precision] decimal places""Status: [Success/Failed]"
Use o pacote strings para dividir as strings de entrada pelas vírgulas, o pacote strconv para converter strings em números, o pacote errors para errors.As e o pacote fmt para encapsulamento e formatação de erros. Este desafio demonstra como tipos de erro personalizados, encapsulamento de erros e 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
1Fluxo de Controle Avançado
Switch com `fallthrough`Interrompendo Loops AninhadosContinuando um Loop EspecíficoA Instrução `goto`Recapitulação - Controle de Loop Avançado4Projeto: Lista de Tarefas Simples
Configuração do ProjetoAdicionando uma Tarefa7Tratamento de Erros em Profundidade
Tipos de Erro PersonalizadosWrapping de Erros com `%w`Unwrapping com `errors.Is`Unwrapping com `errors.As`Entendendo o `panic`Usando o `recover`Recapitulação - Divisão Segura2Structs e Métodos
Definindo Métodos em StructsRecebedores de ValorRecebedores de PonteiroEscolhendo RecebedoresMétodos vs FunçõesRecapitulação - Comportamento de Structs5Mapas em Profundidade
Mapas de StructsPonteiros como Valores de MapVerificando Mapas NilComparando MapasRecapitulação - Contador de Frequência de Palavras3Interfaces (O Básico)
O que é uma Interface?Definindo uma InterfaceImplementando uma InterfaceUsando Tipos de InterfaceInterface VaziaAsserções de TipoType SwitchRecapitulação - Formas e ComportamentosPratique por conta própria: Compilador de Go online