first commit

This commit is contained in:
2026-10-25 20:27:59 +08:00
commit 332b7dcd08
27 changed files with 1708 additions and 0 deletions
+84
View File
@@ -0,0 +1,84 @@
// Package errors 定义业务错误类型与哨兵错误。
// 业务错误携带可被前端消费的业务码(Code),并支持 errors.As 提取。
package errors
import (
stderrors "errors"
"fmt"
)
// BizError 是带业务码的业务错误。
type BizError struct {
Code int
Msg string
Err error
}
func (e *BizError) Error() string {
if e.Err != nil {
return fmt.Sprintf("%s: %v", e.Msg, e.Err)
}
return e.Msg
}
func (e *BizError) Unwrap() error { return e.Err }
// New 构造一个不带原始 error 的业务错误。
func New(code int, msg string) *BizError {
return &BizError{Code: code, Msg: msg}
}
// Wrap 在传播错误时附加上下文与业务码,保留错误链路。
func Wrap(code int, msg string, err error) *BizError {
return &BizError{Code: code, Msg: msg, Err: err}
}
// Is 判断 err 链中是否包含 target,语义与标准库 errors.Is 一致。
// 它沿 Unwrap 链遍历,因此能正确识别被 Wrap 包装后的目标错误
// (如 gorm.ErrRecordNotFound 或本包的哨兵错误 ErrNotFound)。
func Is(err, target error) bool {
return stderrors.Is(err, target)
}
// 常用哨兵错误,供各层直接引用。
var (
ErrBadRequest = New(40000, "bad request")
ErrUnauthorized = New(40100, "unauthorized")
ErrForbidden = New(40300, "forbidden")
ErrNotFound = New(40400, "not found")
ErrServer = New(50000, "internal server error")
)
// CodeOf 从 err 中提取业务码,非业务错误返回 50000。
func CodeOf(err error) int {
var be *BizError
if err != nil && asBizError(err, &be) {
return be.Code
}
return 50000
}
// MsgOf 从 err 中提取可读消息,非业务错误返回内部错误提示。
func MsgOf(err error) string {
var be *BizError
if err != nil && asBizError(err, &be) {
return be.Msg
}
return "internal server error"
}
// asBizError 兼容被 fmt.Errorf("%w") 包装后的 BizError。
func asBizError(err error, target **BizError) bool {
for err != nil {
if b, ok := err.(*BizError); ok {
*target = b
return true
}
u, ok := err.(interface{ Unwrap() error })
if !ok {
return false
}
err = u.Unwrap()
}
return false
}