Riepilogo - Divisione sicura
Fa parte della sezione Logica e flusso del percorso GO di Coddy. Lezione 44 di 68.
Sfida
FacileRealizza una calcolatrice matematica completa che implementi la divisione sicura con diversi tipi di errore personalizzati e una corretta gestione degli errori. Questa sfida combina tipi di errore personalizzati, wrapping degli errori e verifica degli errori per creare un sistema robusto che gestisca con eleganza i vari errori delle operazioni matematiche.
Riceverai due input:
- Una stringa contenente i dettagli dell'operazione nel formato
"operation,num1,num2,precision"(ad es.,"divide,10,0,2") - Una stringa contenente le impostazioni della calcolatrice nel formato
"calculator_name,mode"(ad es.,"ScientificCalc,strict")
Il tuo compito è:
- Creare due tipi di errore personalizzati:
- struct
DivisionErrorcon i campiDividend(float64) eDivisor(float64) - struct
ValidationErrorcon i campiField(string) eValue(float64)
- struct
- Implementare il metodo
Error() stringperDivisionError, che restituisce:"division error: cannot divide [dividend] by [divisor]" - Implementare il metodo
Error() stringperValidationError, che restituisce:"validation error: invalid [field] value [value]" - Analizzare il primo input dividendolo in corrispondenza delle virgole per ottenere operation, num1, num2 e precision
- Analizzare il secondo input dividendolo in corrispondenza delle virgole per ottenere il nome della calcolatrice e la modalità
- Convertire i numeri in formato stringa in float64 e precision in int
- Creare una funzione
safeDivideche accetta due parametri float64 e restituisce (float64, error):- Se divisor è 0, restituire 0 e un
DivisionErrorcon i valori di dividend e divisor - Se dividend è negativo e mode è
"strict", restituire 0 e unValidationErrorcon il campo"dividend"e il valore di dividend - Se divisor è negativo e mode è
"strict", restituire 0 e unValidationErrorcon il campo"divisor"e il valore di divisor - Altrimenti, restituire il risultato della divisione e nil
- Se divisor è 0, restituire 0 e un
- Creare una funzione
performCalculationche esegua il wrapping del risultato disafeDivide:- Se
safeDividerestituisce un errore, eseguirne il wrapping con:"calculation failed in [calculator_name]: %w" - Se l'operazione riesce, restituire il risultato e nil
- Se
- Chiamare
performCalculatione gestire il risultato:- Se non ci sono errori: stampare
"Calculation successful: [result_formatted_to_precision_decimal_places]" - Se si verifica un errore: stampare
"Calculation failed: [error_message]"
- Se non ci sono errori: stampare
- Usare
errors.Asper verificare la presenza di tipi di errore specifici nell'errore sottoposto a wrapping:- Stampare
"Checking for division error: [true/false]" - Stampare
"Checking for validation error: [true/false]"
- Stampare
- Se viene trovato un
DivisionError, stamparne i dettagli:"Division Error Details:""Dividend: [dividend]""Divisor: [divisor]"
- Se viene trovato un
ValidationError, stamparne i dettagli:"Validation Error Details:""Field: [field]""Value: [value]"
- Visualizzare un riepilogo finale:
"Calculator Summary:""Name: [calculator_name]""Mode: [mode]""Operation: [operation]""Input: [num1] [operation_symbol] [num2]"dove operation_symbol è "/" per la divisione"Precision: [precision] decimal places""Status: [Success/Failed]"
Usa il pacchetto strings per dividere le stringhe di input in corrispondenza delle virgole, il pacchetto strconv per convertire le stringhe in numeri, il pacchetto errors per errors.As e il pacchetto fmt per il wrapping e la formattazione degli errori. Questa sfida mostra come i tipi di errore personalizzati, il wrapping degli errori e la corretta verifica degli errori collaborino per creare sistemi di gestione degli errori robusti, in grado di fornire informazioni dettagliate sui diversi tipi di problemi.
Provalo tu
package main
import (
"errors"
"fmt"
"strconv"
"strings"
)
func main() {
// Leggi l'input
var operationInput string
var settingsInput string
fmt.Scanln(&operationInput)
fmt.Scanln(&settingsInput)
// Analizza l'input dell'operazione (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])
// Analizza l'input delle impostazioni (calculator_name,mode)
settingsParts := strings.Split(settingsInput, ",")
calculatorName := settingsParts[0]
mode := settingsParts[1]
// TODO: Scrivi il tuo codice qui sotto
// 1. Crea le struct DivisionError e ValidationError con metodi Error()
// 2. Implementa la funzione safeDivide
// 3. Implementa la funzione performCalculation
// 4. Chiama performCalculation e gestisci i risultati
// 5. Usa errors.As per verificare la presenza di tipi di errore specifici
// 6. Stampa i dettagli dell'errore se presente
// 7. Mostra il riepilogo finale
}Tutte le lezioni di Logica e flusso
1Flusso di controllo avanzato
Switch con `fallthrough`Uscire dai cicli annidatiContinuare un ciclo specificoL'istruzione `goto`Riepilogo - Controllo avanzato dei cicli4Progetto: semplice lista di attività
Configurazione del progettoAggiungere un’attività7Gestione degli errori in dettaglio
Tipi di errore personalizzatiAvvolgere gli errori con `%w`Rimuovere il wrapping con `errors.Is`Rimuovere il wrapping con `errors.As`Capire `panic`Usare `recover`Riepilogo - Divisione sicura2Struct e metodi
Definire metodi sugli structReceiver per valoreReceiver con puntatoreScegliere i receiverMetodi vs funzioniRiepilogo - comportamento degli struct5Mappe in dettaglio
Mappe di structPuntatori come valori delle mappeVerificare le mappe nilConfrontare le mappeRiepilogo - Contatore della frequenza delle parole3Interfacce (le basi)
Che cos’è un’interfaccia?Definire un’interfacciaImplementare un’interfacciaUsare i tipi interfacciaInterfaccia vuotaAsserzioni di tipoSwitch di tipoRiepilogo: forme e comportamentiEsercitati da solo: Compilatore Go online