package errors import ( "errors" "fmt" ) // ErrorType представляет тип ошибки type ErrorType string const ( ErrorTypeInvalid ErrorType = "INVALID" ErrorTypeNotFound ErrorType = "NOT_FOUND" ErrorTypeConflict ErrorType = "CONFLICT" ErrorTypeInternal ErrorType = "INTERNAL" ErrorTypeUnauthorized ErrorType = "UNAUTHORIZED" ErrorTypeForbidden ErrorType = "FORBIDDEN" ) // AppError - кастомная ошибка приложения type AppError struct { Type ErrorType `json:"type"` Message string `json:"message"` Code int `json:"code,omitempty"` Err error `json:"-"` } // Error реализует интерфейс error func (e *AppError) Error() string { if e.Err != nil { return fmt.Sprintf("%s: %v", e.Message, e.Err) } return e.Message } // Unwrap для поддержки errors.Unwrap func (e *AppError) Unwrap() error { return e.Err } // WithCode добавляет HTTP код к ошибке func (e *AppError) WithCode(code int) *AppError { e.Code = code return e } // Wrap оборачивает существующую ошибку func (e *AppError) Wrap(err error) *AppError { e.Err = err return e } // Конструкторы ошибок func NewInvalidError(message string) *AppError { return &AppError{ Type: ErrorTypeInvalid, Message: message, Code: 400, } } func NewNotFoundError(message string) *AppError { return &AppError{ Type: ErrorTypeNotFound, Message: message, Code: 404, } } func NewInternalError(message string) *AppError { return &AppError{ Type: ErrorTypeInternal, Message: message, Code: 500, } } func NewConflictError(message string) *AppError { return &AppError{ Type: ErrorTypeConflict, Message: message, Code: 409, } } // Вспомогательные функции для проверки типов ошибок func IsNotFound(err error) bool { var appErr *AppError if errors.As(err, &appErr) { return appErr.Type == ErrorTypeNotFound } return false } func IsInvalid(err error) bool { var appErr *AppError if errors.As(err, &appErr) { return appErr.Type == ErrorTypeInvalid } return false } func IsConflict(err error) bool { var appErr *AppError if errors.As(err, &appErr) { return appErr.Type == ErrorTypeConflict } return false } // Wrap оборачивает ошибку с сообщением func Wrap(err error, message string) error { return fmt.Errorf("%s: %w", message, err) } func Wrapf(err error, format string, args ...interface{}) error { return fmt.Errorf("%s: %w", fmt.Sprintf(format, args...), err) }