En Go es idiomático comunicar errores a través de un
valor de retorno explícito y separado. Esto contrasta con
las excepciones usadas en lenguajes como Java y Ruby y
el valor único sobrecargado de resultado / error a veces
utilizado en C. El enfoque de Go facilita ver qué
funciones devuelven errores y manejarlos usando los
mismos constructos del lenguaje empleados para cualquier otra
tarea no relacionada con errores.
|
|
|
package main
|
|
import (
"errors"
"fmt"
)
|
Por convención, los errores son el último valor de retorno y
tienen el tipo error , una interfaz incorporada.
|
func f1(arg int) (int, error) {
if arg == 42 {
|
errors.New() construye un valor básico de error
con el mensaje de error dado.
|
return -1, errors.New("can't work with 42")
|
|
}
|
Un valor nil en la posición del error indica que
no hubo error.
|
return arg + 3, nil
}
|
Es posible usar tipos personalizados como error s implementando el método Error()
en ellos.
Aquí hay una variante del ejemplo anterior que usa un tipo personalizado
para representar explícitamente un error de argumento.
|
type argError struct {
arg int
prob string
}
|
|
func (e *argError) Error() string {
return fmt.Sprintf("%d - %s", e.arg, e.prob)
}
|
|
func f2(arg int) (int, error) {
if arg == 42 {
|
En este caso, usamos la sintaxis &argError para construir
una nueva estructura, suministrando valores para los dos
campos arg y prob .
|
return -1, &argError{arg, "can't work with it"}
}
return arg + 3, nil
}
|
|
func main() {
|
Los dos bucles a continuación prueban cada una de nuestras
funciones que devuelven errores. Observa que el uso de una
verificación de error en la línea del if es un idiomatismo común en el código de Go.
|
for _, i := range []int{7, 42} {
if r, e := f1(i); e != nil {
fmt.Println("f1 failed:", e)
} else {
fmt.Println("f1 worked:", r)
}
}
for _, i := range []int{7, 42} {
if r, e := f2(i); e != nil {
fmt.Println("f2 failed:", e)
} else {
fmt.Println("f2 worked:", r)
}
}
|
Si quieres usar programáticamente los datos en
un error personalizado, necesitarás obtener el error como una
instancia del tipo de error personalizado mediante una
afirmación de tipo.
|
_, e := f2(42)
if ae, ok := e.(*argError); ok {
fmt.Println(ae.arg)
fmt.Println(ae.prob)
}
}
|