Go fue diseñado desde el principio para devolver errores de manera explícita en lugar de usar excepciones. Esto permite escribir código predecible y evitar trampas ocultas propias de las construcciones try/catch de otros lenguajes (por ejemplo, Java o C++). Un error en Go es una interfaz que implementa el método Error(), lo que permite crear errores tanto simples como complejos/envueltos con contexto.
Los problemas surgen cuando los errores se manejan incorrectamente (por ejemplo, si se ignoran a través de _ o no se envuelven con información adicional para depuración) o al crear "errores mágicos" que no cumplen con la interfaz error. También es importante devolver errores desde funciones públicas y verificarlos en cada llamada.
La solución es utilizar enfoques estándar:
Ejemplo de código:
import ( "errors" "fmt" ) type NotFoundError struct { Resource string } func (e *NotFoundError) Error() string { return fmt.Sprintf("%s no encontrado", e.Resource) } func GetUser(id int) (string, error) { if id != 1 { return "", &NotFoundError{"Usuario"} } return "Steve", nil } func main() { user, err := GetUser(2) if err != nil { if nfe, ok := err.(*NotFoundError); ok { fmt.Println(nfe.Resource, "problema") } else { fmt.Println("error:", err) } } fmt.Println("usuario:", user) }
Características clave:
¿Se puede hacer una comparación de error mediante ==, o se deben usar métodos especiales?
Es mejor usar siempre errors.Is() para comparar con errores-envoltura, de lo contrario, la comparación mediante == puede no funcionar si hay un envoltorio de error.
if errors.Is(err, os.ErrNotExist) { // manejo de la falta de archivo }
¿Es obligatorio implementar un tipo-struct para un error personalizado, o es suficiente con usar errors.New("...")?
Si solo se necesita el texto del error, es suficiente con errors.New(). Si es importante mantener el contexto (por ejemplo, el nombre del recurso), es mejor definir un struct con un método Error().
¿Cómo devolver correctamente un error en caso de éxito en la ejecución de la función?
En caso de éxito, siempre devuelva un error nil.
return result, nil
Caso negativo
Un desarrollador escribe una función que devuelve un error sin explicaciones (simplemente errors.New("fallo")). Al analizar los registros, no se puede establecer la causa.
Ventajas:
Desventajas:
Caso positivo
Un desarrollador define un tipo de error personalizado NotFoundError y lo devuelve con una descripción detallada.
Ventajas:
Desventajas: