En Go, no existe un mecanismo especial para vincular métodos directamente a los tipos de error. Los errores en Go son simplemente valores que cumplen con la interfaz error, que tiene un solo método, Error() string. Por lo tanto, cualquier tipo que implemente este método puede utilizarse como un error en Go.
Si eres nuevo en el mundo de Go te recomiendo los siguientes artÃculos anteriores:
Lo primero que debmos saber es que en Go el valor de error retornado por una función debe ser siempre el último, por ejemplo:
func f1(arg int) (int, error) {
if arg == 42 {
return -1, errors.New("can't work with 42")
}
return arg + 3, nil
}
Podemos programar errores custom de forma muy sencilla tan solo debemos implementar la interfaz error, que tiene un solo método, Error() string. Por lo tanto creamos una estructura con los campos que requiramos, esta estructura quedará vinculada a la función Error() debido a los
Go methods
de Go, acto seguido en la función f2
creamos un objeto de tipo argError pasándole como parámetros los valores esperados por la estructura:
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 {
return -1, &argError{arg, "can't work with it"}
}
return arg + 3, nil
}
Si no queremos mostrar el error tal cual viene de nuestra función de Error, podemos capturar el error y acceder a cada uno de los datos de la estructura, en este caso el error es capturado en la variable e
y luego volcamos los campos en la variable fieldsStructure que tiene los campos definidos en la estructura argError, el segundo parámetro de retorno indica si el volcado ha sido satisfactorio o no, en caso positivo imprimimos los datos:
_, e := f2(42)
if fieldsStructure, ok := e.(*argError); ok {
fmt.Println(fieldsStructure.arg)
fmt.Println(fieldsStructure.prob)
}
Veamos el ejemplo completo:
package main
import (
"errors"
"fmt"
)
func f1(arg int) (int, error) {
if arg == 42 {
return -1, errors.New("can't work with 42")
}
return arg + 3, nil
}
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 {
return -1, &argError{arg, "can't work with it"}
}
return arg + 3, nil
}
func main() {
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)
}
}
_, e := f2(42)
if fieldsStructure, ok := e.(*argError); ok {
fmt.Println(fieldsStructure.arg)
fmt.Println(fieldsStructure.prob)
}
}
Ejecutamos el código:
f1 worked: 10
f1 failed: can't work with 42
f2 worked: 10
f2 failed: 42 - can't work with it
42
can't work with it