awesome-back/pkg/errors/errors.go

136 lines
3.0 KiB
Go
Raw Normal View History

2025-10-16 12:55:36 +03:00
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"
2025-10-16 13:23:45 +03:00
ErrorTypeNetwork ErrorType = "NETWORK"
2025-10-16 12:55:36 +03:00
)
// 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,
}
}
2025-10-16 13:23:45 +03:00
func NewNetworkError(message string) *AppError {
return &AppError{
Type: ErrorTypeNetwork,
Message: message,
Code: 0, // Network errors don't have HTTP codes
}
}
2025-10-16 12:55:36 +03:00
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
}
2025-10-16 14:19:39 +03:00
func IsNetworkError(err error) bool {
var appErr *AppError
if errors.As(err, &appErr) {
return appErr.Type == ErrorTypeNetwork
}
return false
}
2025-10-16 12:55:36 +03:00
// 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)
}