thread-master/backend/internal/library/errors/errors.go

170 lines
3.5 KiB
Go
Raw Normal View History

2026-06-26 08:37:04 +00:00
package errors
import (
"errors"
"fmt"
"net/http"
"haixun-backend/internal/library/errors/code"
)
type Error struct {
scope code.Scope
category code.Category
detail code.Detail
message string
cause error
}
func New(scope code.Scope, category code.Category, detail code.Detail, message string) *Error {
return &Error{scope: scope, category: category, detail: detail, message: message}
}
func FromError(err error) *Error {
var e *Error
if errors.As(err, &e) {
return e
}
return nil
}
func (e *Error) Error() string {
if e == nil {
return ""
}
return e.message
}
func (e *Error) Unwrap() error {
if e == nil {
return nil
}
return e.cause
}
func (e *Error) WithCause(cause error) *Error {
if e == nil {
return nil
}
cp := *e
cp.cause = cause
return &cp
}
func (e *Error) Scope() code.Scope {
if e == nil {
return code.Unset
}
return e.scope
}
func (e *Error) Category() code.Category {
if e == nil {
return code.SysInternal
}
return e.category
}
func (e *Error) Detail() code.Detail {
if e == nil {
return code.DefaultDetail
}
return e.detail
}
func (e *Error) Code() uint32 {
if e == nil {
return 0
}
return uint32(e.scope)*code.ScopeMultiplier + uint32(e.category)*code.CategoryMultiplier + uint32(e.detail)
}
func (e *Error) DisplayCode() string {
if e == nil {
return "00000000"
}
return fmt.Sprintf("%08d", e.Code())
}
func (e *Error) HTTPStatus() int {
if e == nil {
return http.StatusInternalServerError
}
switch e.category {
case code.InputInvalidFormat, code.InputMissingRequired:
return http.StatusBadRequest
case code.DBUnavailable:
return http.StatusServiceUnavailable
case code.ResNotFound:
return http.StatusNotFound
case code.ResConflict:
return http.StatusConflict
case code.ResInvalidState:
return http.StatusConflict
case code.AuthUnauthorized:
return http.StatusUnauthorized
case code.AuthForbidden:
return http.StatusForbidden
case code.SvcThirdParty:
return http.StatusBadGateway
default:
return http.StatusInternalServerError
}
}
type Builder struct {
scope code.Scope
}
func For(scope code.Scope) Builder {
return Builder{scope: scope}
}
func (b Builder) InputInvalidFormat(message string) *Error {
return New(b.scope, code.InputInvalidFormat, 0, message)
}
func (b Builder) InputMissingRequired(message string) *Error {
return New(b.scope, code.InputMissingRequired, 0, message)
}
func (b Builder) DBError(message string) *Error {
return New(b.scope, code.DBError, 0, message)
}
func (b Builder) DBUnavailable(message string) *Error {
return New(b.scope, code.DBUnavailable, 0, message)
}
func (b Builder) ResNotFound(message string) *Error {
return New(b.scope, code.ResNotFound, 0, message)
}
func (b Builder) ResConflict(message string) *Error {
return New(b.scope, code.ResConflict, 0, message)
}
func (b Builder) ResInvalidState(message string) *Error {
return New(b.scope, code.ResInvalidState, 0, message)
}
func (b Builder) AuthUnauthorized(message string) *Error {
return New(b.scope, code.AuthUnauthorized, 0, message)
}
func (b Builder) AuthForbidden(message string) *Error {
return New(b.scope, code.AuthForbidden, 0, message)
}
func (b Builder) SysInternal(message string) *Error {
return New(b.scope, code.SysInternal, 0, message)
}
func (b Builder) SysNotImplemented(message string) *Error {
return New(b.scope, code.SysNotImplemented, 0, message)
}
func (b Builder) SvcThirdParty(message string) *Error {
return New(b.scope, code.SvcThirdParty, 0, message)
}