99 lines
2.2 KiB
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)
|
|
}
|
|
}
|