package errcode import ( "fmt" "net/http" ) // Error 业务错误 type Error struct { code int msg string details []string } // codes 用于注册时去重检查 var codes = map[int]string{} // NewError 注册并创建一个错误码 func NewError(code int, msg string) *Error { if _, exists := codes[code]; exists { panic(fmt.Sprintf("error code %d already exists, please change", code)) } codes[code] = msg return &Error{code: code, msg: msg} } func (e *Error) Error() string { return fmt.Sprintf("error code: %d, msg: %s", e.code, e.msg) } func (e *Error) Code() int { return e.code } func (e *Error) Msg() string { return e.msg } func (e *Error) Details() []string { return e.details } func (e *Error) Msgf(args ...interface{}) string { return fmt.Sprintf(e.msg, args...) } // WithDetails 附加详细信息(返回副本) func (e *Error) WithDetails(details ...string) *Error { newError := *e newError.details = append(newError.details, details...) return &newError } // StatusCode 业务码 → HTTP 状态码 // 仅对少数特殊错误返回非 200,其余统一 200,由前端按业务 code 处理 func (e *Error) StatusCode() int { switch e.code { case Success.Code(): return http.StatusOK // 鉴权类返回 401,便于前端拦截器统一处理跳转登录 case Unauthorized.Code(), UnauthorizedTokenError.Code(), UnauthorizedTokenTimeout.Code(), UnauthorizedTokenMissing.Code(): return http.StatusUnauthorized // 越权/无权限返回 403,便于网关与审计识别越权事件 case Forbidden.Code(): return http.StatusForbidden // 限流返回 429,便于网关识别限流事件 case TooManyRequests.Code(): return http.StatusTooManyRequests // 系统错误返回 500,便于运维监控告警 case ServerError.Code(), DatabaseError.Code(), CacheError.Code(), RPCError.Code(), UnknownError.Code(), MattingFailed.Code(), ClassifyFailed.Code(): return http.StatusInternalServerError } return http.StatusOK }