package errors import ( "fmt" "runtime" "strings" "github.com/pkg/errors" ) // Error es una interfaz extendida para errores type Error interface { error Code() string Unwrap() error } // CustomError implementa la interfaz Error type CustomError struct { code string message string cause error stack []uintptr } // New crea un nuevo error personalizado func New(code, message string) Error { return &CustomError{ code: code, message: message, stack: callers(), } } // Wrap envuelve un error con información adicional func Wrap(err error, message string) Error { if err == nil { return nil } return &CustomError{ code: extractCode(err), message: message, cause: err, stack: callers(), } } // Wrapf envuelve un error con un mensaje formateado func Wrapf(err error, format string, args ...interface{}) Error { if err == nil { return nil } return &CustomError{ code: extractCode(err), message: fmt.Sprintf(format, args...), cause: err, stack: callers(), } } // NewWithCode crea un nuevo error con un código específico func NewWithCode(code, message string) Error { return &CustomError{ code: code, message: message, stack: callers(), } } // Error implementa la interfaz error func (e *CustomError) Error() string { if e.cause != nil { return fmt.Sprintf("%s: %v", e.message, e.cause) } return e.message } // Code retorna el código de error func (e *CustomError) Code() string { return e.code } // Unwrap implementa la interfaz de unwrapping func (e *CustomError) Unwrap() error { return e.cause } // Stack retorna la pila de llamadas func (e *CustomError) Stack() string { var sb strings.Builder frames := runtime.CallersFrames(e.stack) for { frame, more := frames.Next() sb.WriteString(fmt.Sprintf("%s:%d %s\n", frame.File, frame.Line, frame.Function)) if !more { break } } return sb.String() } // extractCode extrae el código de un error func extractCode(err error) string { if customErr, ok := err.(Error); ok { return customErr.Code() } return "UNKNOWN" } // callers obtiene la pila de llamadas func callers() []uintptr { const depth = 32 var pcs [depth]uintptr n := runtime.Callers(3, pcs[:]) return pcs[0:n] } // Errores comunes var ( ErrNotFound = NewWithCode("NOT_FOUND", "recurso no encontrado") ErrUnauthorized = NewWithCode("UNAUTHORIZED", "no autorizado") ErrForbidden = NewWithCode("FORBIDDEN", "acceso prohibido") ErrBadRequest = NewWithCode("BAD_REQUEST", "solicitud incorrecta") ErrInternal = NewWithCode("INTERNAL", "error interno del servidor") ErrTimeout = NewWithCode("TIMEOUT", "tiempo de espera agotado") ErrNotImplemented = NewWithCode("NOT_IMPLEMENTED", "no implementado") )