Menu
Coddy logo textTech

La interfaz error

Parte de la sección Programación Orientada a Objetos del Journey de GO de Coddy. Lección 52 de 107.

En Go, los errors se gestionan mediante una interface integrada llamada error. Esta interface es extraordinariamente sencilla. Solo requiere un método:

type error interface {
    Error() string
}

Cualquier tipo que implemente un método Error() que devuelva una cadena satisface automáticamente la interfaz error. Este es el sistema de interfaces de Go en acción: no se necesita ninguna declaración explícita.

La forma más común de crear errores es usar el paquete 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
}

Las funciones de Go normalmente devuelven un error como su último valor de retorno. Cuando no ocurre ningún error, devuelves nil. Después, quien realiza la llamada comprueba si el error no es nil antes de continuar:

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

También puedes usar fmt.Errorf para crear mensajes de error con formato:

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

Este patrón de devolver errores en lugar de lanzar excepciones es fundamental en Go. Hace que el manejo de errores sea explícito y te obliga a considerar qué sucede cuando las cosas salen mal: un aspecto clave para escribir código robusto y orientado a objetos.

challenge icon

Desafío

Fácil

Construyamos un sistema de cuentas bancarias que demuestre el patrón de manejo de errores de Go. Crearás una cuenta sencilla que valida las operaciones y devuelve errores significativos cuando algo sale mal.

Organizarás tu código en dos archivos:

  • account.go: Crea una estructura BankAccount con un campo Owner exportado (string) y un campo balance no exportado (float64). Implementa lo siguiente:
    • NewBankAccount(owner string, initialDeposit float64) (*BankAccount, error): un constructor que devuelve un error con el mensaje "initial deposit must be positive" si el depósito inicial es cero o negativo. De lo contrario, crea y devuelve la cuenta.
    • Deposit(amount float64) error: añade dinero al saldo. Devuelve un error con el mensaje "deposit amount must be positive" si el importe es cero o negativo.
    • Withdraw(amount float64) error: retira dinero del saldo. Devuelve un error con el mensaje "withdrawal amount must be positive" si el importe es cero o negativo, o "insufficient funds" si el saldo es menor que el importe del retiro.
    • Balance() float64: devuelve el saldo actual
  • main.go: Lee los datos de la cuenta y los importes de las transacciones de la entrada. Intenta crear una cuenta y realizar operaciones. Después de cada operación, imprime el mensaje de éxito o el mensaje de error.

Se proporcionarán las siguientes entradas:

  • Línea 1: Nombre del propietario
  • Línea 2: Importe del depósito inicial
  • Línea 3: Importe del depósito
  • Línea 4: Importe del retiro

Para cada operación, imprime el resultado:

  • Después de crear la cuenta: Account created for [Owner] with balance: $[balance] o Error: [error message]
  • Después del depósito: Deposited successfully. New balance: $[balance] o Error: [error message]
  • Después del retiro: Withdrew successfully. New balance: $[balance] o Error: [error message]

Da formato a todos los valores del saldo con dos decimales. Si la creación de la cuenta falla, omite las operaciones restantes.

Por ejemplo, dados Alice, 100, 50 y 200, tu salida debería ser:

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

Y dados Bob, -50, 25 y 10, tu salida debería ser:

Error: initial deposit must be positive

Pruébalo tú mismo

package main

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

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

	// Leer el nombre del propietario
	ownerName, _ := reader.ReadString('\n')
	ownerName = strings.TrimSpace(ownerName)

	// Read initial deposit
	initialDepositStr, _ := reader.ReadString('\n')
	initialDeposit, _ := strconv.ParseFloat(strings.TrimSpace(initialDepositStr), 64)

	// Read deposit amount
	depositStr, _ := reader.ReadString('\n')
	depositAmount, _ := strconv.ParseFloat(strings.TrimSpace(depositStr), 64)

	// Read withdrawal amount
	withdrawStr, _ := reader.ReadString('\n')
	withdrawAmount, _ := strconv.ParseFloat(strings.TrimSpace(withdrawStr), 64)

	// TODO: Crear una nueva cuenta bancaria usando NewBankAccount
	// Si hay un error, imprime "Error: [error message]" y retorna
	// Si es exitoso, imprime "Account created for [Owner] with balance: $[balance]"

	// TODO: Intentar depositar la cantidad del depósito
	// Si hay un error, imprime "Error: [error message]"
	// If successful, print "Deposited successfully. New balance: $[balance]"

	// TODO: Intentar retirar la cantidad del retiro
	// Si hay un error, imprime "Error: [error message]"
	// If successful, print "Withdrew successfully. New balance: $[balance]"

	// Recuerda formatear los valores del balance con dos decimales usando fmt.Printf("%.2f", balance)

	_ = ownerName
	_ = initialDeposit
	_ = depositAmount
	_ = withdrawAmount
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de Go online