Files
bulma/custom_error.go

99 lines
2.2 KiB
Go

package main
import (
"errors"
"fmt"
)
// AppError 全局通用自定义错误
type AppError struct {
Code int // 业务错误码
Msg string // 错误描述
Module string // 所属模块
Status int // HTTP 状态码(可选扩展)
Err error // 底层原始错误(支持错误链)
}
// Error 实现标准 error 接口
func (e *AppError) Error() string {
return fmt.Sprintf("[%s] 错误码:%d | HTTP:%d | 描述:%s", e.Module, e.Code, e.Status, e.Msg)
}
// Unwrap 返回底层错误,支持 errors.Unwrap 和 errors.As 递归解包
func (e *AppError) Unwrap() error {
return e.Err
}
// 模拟数据库操作错误
func dbOperation(id string) error {
if id == "not_found" {
return fmt.Errorf("record [%s] not found: %w", id, errors.New("database empty"))
}
return nil
}
// 模拟业务逻辑
func businessDemo(name string) error {
if name == "invalid" {
return &AppError{
Code: 40010,
Msg: "参数非法",
Module: "user",
Status: 400,
}
}
if name == "db_error" {
dbErr := dbOperation("not_found")
return &AppError{
Code: 50001,
Msg: "数据库操作失败",
Module: "database",
Status: 500,
Err: dbErr, // 包装底层错误
}
}
return nil
}
// 统一错误处理
func parseError(err error) {
var appErr *AppError
// 断言自定义错误
if errors.As(err, &appErr) {
fmt.Printf("捕获业务错误:%+v\n", appErr)
// 如果有底层错误,继续解包
if appErr.Unwrap() != nil {
fmt.Printf("底层错误:%v\n", appErr.Unwrap())
// 使用 errors.Is 检测底层错误
if errors.Is(appErr.Unwrap(), errors.New("database empty")) {
fmt.Println("判定:底层是数据库空错误")
}
}
return
}
// 处理通用错误
if err != nil {
fmt.Printf("捕获系统错误:%v\n", err)
}
}
func main() {
fmt.Println("===== 自定义错误类型 =====")
err := businessDemo("invalid")
parseError(err)
fmt.Println("\n===== 带错误链的自定义错误 =====")
err2 := businessDemo("db_error")
parseError(err2)
fmt.Println("\n===== 使用 errors.As 深度提取 =====")
var appErr *AppError
if errors.As(err2, &appErr) {
fmt.Printf("提取到 AppError - 模块:%s, 错误码:%d\n", appErr.Module, appErr.Code)
}
}