Lección 13 · 13 de 20
Errores como valores · Go
Trate los errores en Go como valores: créelos con errors.New y fmt.Errorf, compruébelos con if err != nil y reconózcalos con errors.Is.

Go no tiene excepciones: una función que puede fallar devuelve un error como último resultado. withdraw devuelve el saldo nuevo y un error; si todo va bien, el error es nil, es decir, «ningún error».
errors.New("insufficient funds") crea un error con un mensaje. Guardado en la variable ErrNoFunds, es un error centinela: un valor conocido con el que se puede comparar después. fmt.Errorf crea un error con formato, igual que Printf: invalid amount -5.00.
Con %w, fmt.Errorf envuelve otro error: el mensaje añade detalle (withdraw 90.00: insufficient funds), pero el error original sigue dentro. errors.Is(err, ErrNoFunds) lo busca, y por eso da true para la retirada de 90 euros y false para la cantidad negativa.
Quien llama comprueba siempre: if err != nil. Si hay error, lo escribe y, con continue, pasa a la cantidad siguiente sin tocar el saldo; si no, guarda newBalance. Así, de 100 euros se sacan 30 y luego 45, y quedan 25.00.
Código · main.go
package mainimport ( "errors" "fmt")// errors.New creates an error value that can be recognised later.var ErrNoFunds = errors.New("insufficient funds")// The error goes last; nil means that everything went well.func withdraw(balance, amount float64) (float64, error) { switch { case amount <= 0: return balance, fmt.Errorf("invalid amount %.2f", amount) case amount > balance: return balance, fmt.Errorf("withdraw %.2f: %w", amount, ErrNoFunds) // %w wraps it } return balance - amount, nil}func main() { balance, amounts := 100.0, []float64{30, -5, 90, 45} for i := 0; i < len(amounts); i++ { newBalance, err := withdraw(balance, amounts[i]) if err != nil { fmt.Println("Error:", err) fmt.Println(" is ErrNoFunds?", errors.Is(err, ErrNoFunds)) continue } balance = newBalance fmt.Printf("Took %.2f, balance %.2f\n", amounts[i], balance) }}Salida · go run main.go
Took 30.00, balance 70.00 Error: invalid amount -5.00 is ErrNoFunds? false Error: withdraw 90.00: insufficient funds is ErrNoFunds? true Took 45.00, balance 25.00
Para recordar
- El error es el último resultado;
nilsignifica que no hubo error. errors.Newcrea un error;fmt.Errorf, uno con formato.%wenvuelve un error dentro de otro.errors.Isreconoce un error aunque esté envuelto.- Compruebe siempre con
if err != nil.
Ejercicio
Añada un límite diario: un error centinela ErrDailyLimit que withdraw devuelva, envuelto con %w, si la cantidad supera 60 euros, y compruébelo en main con errors.Is.