Errores Centinela y errors.Is
Los errores centinela son variables a nivel de paquete que representan una identidad de fallo fija.
Busca en todas las páginas de la documentación
Los errores centinela son variables a nivel de paquete que representan una identidad de fallo fija.
Los llamadores los reconocen con errors.Is en lugar de coincidencias de cadenas o comprobaciones == frágiles que se rompen una vez que los errores se envuelven.
Los errores centinela dan a tu API un pequeño vocabulario de resultados estables: no encontrado, ya existe, cancelado, entrada inválida.
Go 1.13 añadió errors.Is para que esas identidades sobrevivan a las cadenas de envoltura de fmt.Errorf("...: %w", err).
Usa centinelas para contratos entre paquetes; recurre a tipos personalizados cuando los llamadores necesiten campos estructurados.
Tarjeta de receta de referencia rápida - lista para copiar y pegar.
var ErrNotFound = errors.New("not found")
func Find(id string) (Item, error) {
if id == "" {
return Item{}, ErrNotFound
}
return Item{}, nil
}
if errors.Is(err, ErrNotFound) {
// manejar recurso faltante
}Cuándo recurrir a esto:
io.EOF, os.ErrNotExist) se aplican a tu dominiopackage main
import (
"errors"
"fmt"
"os"
)
var ErrUserNotFound = errors.New("user not found")
func loadUser(path string) error {
_, err := os.ReadFile(path)
if err != nil {
if os.IsNotExist(err) {
return fmt.Errorf("load user %q: %w", path, ErrUserNotFound)
}
return fmt.Errorf("load user %q: %w", path, err)
}
return nil
}
func main() {
err := loadUser("alice.json")
switch {
case errors.Is(err, ErrUserNotFound):
fmt.Println("client: 404 user missing")
case err != nil:
fmt.Println("client: 500", err)
default:
fmt.Println("ok")
}
}Lo que esto demuestra:
ErrUserNotFound) se mapea a un resultado del clientefmt.Errorf con %w preserva tanto los centinelas de os como los de dominio en la cadenaerrors.Is encuentra ErrUserNotFound a través de las envolturasos.IsNotExist es un envoltorio de conveniencia alrededor de errors.Is(err, os.ErrNotExist)errors.New devuelve un valor de error opaco con una identidad fija.%w implementa Unwrap() error, enlazando errores externos e internos.errors.Is(err, target) devuelve verdadero si err == target o cualquier paso de desempaquetado coincide.err == ErrX directo falla cuando un envoltorio se interpone entre el llamador y el centinela.| Patrón | Ejemplo | Guía |
|---|---|---|
| Centinela exportado | var ErrNotFound = errors.New(...) | Parte del contrato público |
| Centinela no exportado | var errStale = errors.New(...) | Solo interno del paquete |
| Biblioteca estándar | io.EOF, context.Canceled | Usa errors.Is, no strings.Contains |
io.EOF señala el fin del flujo durante Read, no necesariamente un fallo catastrófico.
Bucle hasta errors.Is(err, io.EOF) después de procesar el último fragmento.
// Malo: se rompe después de envolver
if err == ErrNotFound { ... }
// Bueno
if errors.Is(err, ErrNotFound) { ... }
// También bueno para ayudantes de la biblioteca estándar
if os.IsNotExist(err) { ... }== después de envolver - Los errores envueltos nunca son iguales al centinela. Solución: Usa errors.Is.ErrX se vuelven difíciles de documentar. Solución: Agrupa fallos relacionados en un tipo de error o un enum de códigos de error.strings.Contains - Frágil a través de envolturas y cambios de redacción. Solución: errors.Is o errors.As.return (*MyError)(nil) hace que err != nil sea verdadero. Solución: return nil o var err error = nil.errors.Is(err, io.EOF) por separado de los errores reales.| Alternativa | Usar Cuando | No Usar Cuando |
|---|---|---|
Estructura personalizada + errors.As | Los llamadores necesitan campos (nombre de campo, reintentable) | Solo se necesita una rama sí/no |
| Códigos de error en un tipo | Muchas variantes relacionadas comparten forma | Cada variante es verdaderamente independiente |
| Errores opacos | Ocultar la implementación a los llamadores | Los llamadores deben ramificar en causas específicas |
fmt.Errorf sin %w | La causa interna no debe ser inspeccionable | Los llamadores necesitan errors.Is a través de la cadena |
Un valor var ErrX = errors.New("...") a nivel de paquete con identidad estable. Los llamadores lo reconocen con errors.Is.
Envolver crea un nuevo valor de error cuyo objetivo de comparación directa es el envoltorio, no el centinela. errors.Is recorre Unwrap.
Exporta solo los errores que formen parte de tu API documentada. Mantén los fallos internos sin exportar u opacos.
Usa el prefijo Err y PascalCase: ErrNotFound, ErrConflict. Sigue el estilo de la biblioteca estándar de Go.
Sí. errors.Is(err, io.EOF) es la comprobación idiomática en bucles de lectura y funciona a través de envolturas.
os.IsNotExist es un ayudante que comprueba os.ErrNotExist (y envolturas) en cualquier error. errors.Is es el mecanismo general.
Devuelve centinelas (o errores tipados) para los resultados del contrato; envuelve con contexto usando fmt.Errorf y %w en cada capa.
Si necesitas una tabla para explicarlos, considera un tipo de error con un campo de código o tipos separados por categoría.
Sí. errors.Is comprueba cada error en un valor unido (Go 1.20+).
Cuando el error envuelto no debe ser visible para Is/As, como al sanitizar mensajes en un límite de API pública.
Es un valor error utilizado para el flujo de control al final de la entrada. Manéjalo explícitamente en lugar de registrarlo como un fallo.
Mapea con errors.Is en los manejadores: no encontrado a 404, conflicto a 409. Mantén el mapeo en el límite del transporte.
Versiones de Stack: Esta página fue escrita para Go 1.26.x (predeterminado GC Green Tea, go fix modernizers - verificar parche en la compilación), chi (última - verificar en la compilación), gin (última - verificar en la compilación), echo (última - verificar en la compilación), google.golang.org/grpc (última - verificar en la compilación), sigs.k8s.io/controller-runtime (última - verificar en la compilación), kubebuilder (última - verificar en la compilación), tinygo (última - verificar objetivos de placa en la compilación), wazero (última - verificar en la compilación) y golangci-lint (última - verificar conjunto de linters en la compilación).
Revisado por Chris St. John·Última actualización: 16 jul 2026