Menu
Coddy logo textTech

L'interfaccia error

Fa parte della sezione Programmazione orientata agli oggetti del percorso GO di Coddy. Lezione 52 di 107.

In Go, gli errori vengono gestiti tramite un'interfaccia integrata chiamata error. Questa interfaccia è straordinariamente semplice. Richiede un solo metodo:

type error interface {
    Error() string
}

Qualsiasi tipo che implementa un metodo Error() che restituisce una stringa soddisfa automaticamente l’interfaccia error. Questo è il sistema di interfacce di Go in azione: non è necessaria alcuna dichiarazione esplicita.

Il modo più comune per creare errori è usare il pacchetto errors:

import "errors"

func Divide(a, b int) (int, error) {
    if b == 0 {
        return 0, errors.New("cannot divide by zero")
    }
    return a / b, nil
}

Le funzioni Go in genere restituiscono un errore come ultimo valore restituito. Quando non si verifica alcun errore, restituisci nil. Chi chiama la funzione controlla quindi se l’errore è diverso da nil prima di procedere:

result, err := Divide(10, 0)
if err != nil {
    fmt.Println("Error:", err.Error())
    return
}
fmt.Println("Result:", result)

Puoi anche usare fmt.Errorf per creare messaggi di errore formattati:

func GetUser(id int) (string, error) {
    if id <= 0 {
        return "", fmt.Errorf("invalid user id: %d", id)
    }
    return "Alice", nil
}

Questo modello di restituzione degli errori anziché di generazione di eccezioni è fondamentale in Go. Rende esplicita la gestione degli errori e ti costringe a considerare cosa succede quando qualcosa va storto: un aspetto chiave della scrittura di codice robusto e orientato agli oggetti.

challenge icon

Sfida

Facile

Costruiamo un sistema di conti bancari che mostri il modello di gestione degli errori di Go. Creerai un conto semplice che convalida le operazioni e restituisce errori significativi quando qualcosa va storto.

Organizzerai il codice in due file:

  • account.go: crea una struct BankAccount con un campo Owner esportato (string) e un campo balance non esportato (float64). Implementa quanto segue:
    • NewBankAccount(owner string, initialDeposit float64) (*BankAccount, error) - un costruttore che restituisce un errore con il messaggio "initial deposit must be positive" se il deposito iniziale è zero o negativo. Altrimenti, crea e restituisce il conto.
    • Deposit(amount float64) error - aggiunge denaro al saldo. Restituisce un errore con il messaggio "deposit amount must be positive" se l'importo è zero o negativo.
    • Withdraw(amount float64) error - preleva denaro dal saldo. Restituisce un errore con il messaggio "withdrawal amount must be positive" se l'importo è zero o negativo, oppure "insufficient funds" se il saldo è inferiore all'importo del prelievo.
    • Balance() float64 - restituisce il saldo attuale
  • main.go: leggi i dettagli del conto e gli importi delle transazioni dall'input. Prova a creare un conto ed eseguire le operazioni. Dopo ogni operazione, stampa il messaggio di successo oppure il messaggio di errore.

Verranno forniti i seguenti input:

  • Riga 1: nome del titolare
  • Riga 2: importo del deposito iniziale
  • Riga 3: importo del deposito
  • Riga 4: importo del prelievo

Per ogni operazione, stampa il risultato:

  • Dopo la creazione del conto: Account created for [Owner] with balance: $[balance] oppure Error: [error message]
  • Dopo il deposito: Deposited successfully. New balance: $[balance] oppure Error: [error message]
  • Dopo il prelievo: Withdrew successfully. New balance: $[balance] oppure Error: [error message]

Formatta tutti i valori del saldo con due cifre decimali. Se la creazione del conto non riesce, salta le operazioni rimanenti.

Ad esempio, con Alice, 100, 50 e 200, l'output dovrebbe essere:

Account created for Alice with balance: $100.00
Deposited successfully. New balance: $150.00
Error: insufficient funds

E con Bob, -50, 25 e 10, l'output dovrebbe essere:

Error: initial deposit must be positive

Provalo tu

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	reader := bufio.NewReader(os.Stdin)

	// Leggi il nome del titolare
	ownerName, _ := reader.ReadString('\n')
	ownerName = strings.TrimSpace(ownerName)

	// Leggi il deposito iniziale
	initialDepositStr, _ := reader.ReadString('\n')
	initialDeposit, _ := strconv.ParseFloat(strings.TrimSpace(initialDepositStr), 64)

	// Leggi l'importo da depositare
	depositStr, _ := reader.ReadString('\n')
	depositAmount, _ := strconv.ParseFloat(strings.TrimSpace(depositStr), 64)

	// Leggi l'importo da prelevare
	withdrawStr, _ := reader.ReadString('\n')
	withdrawAmount, _ := strconv.ParseFloat(strings.TrimSpace(withdrawStr), 64)

	// TODO: Crea un nuovo conto bancario usando NewBankAccount
	// Se si verifica un errore, stampa "Error: [error message]" e termina
	// Se l'operazione riesce, stampa "Account created for [Owner] with balance: $[balance]"

	// TODO: Prova a depositare l'importo indicato
	// Se si verifica un errore, stampa "Error: [error message]"
	// Se l'operazione riesce, stampa "Deposited successfully. New balance: $[balance]"

	// TODO: Prova a prelevare l'importo indicato
	// Se si verifica un errore, stampa "Error: [error message]"
	// Se l'operazione riesce, stampa "Withdrew successfully. New balance: $[balance]"

	// Ricorda di formattare i saldi con due cifre decimali usando fmt.Printf("%.2f", balance)

	_ = ownerName
	_ = initialDeposit
	_ = depositAmount
	_ = withdrawAmount
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore Go online