辅助中间件
Panic 恢复
PanicRecovery 捕获异常并返回统一错误响应
Panic 恢复
PanicRecovery 全局 Panic 捕获与恢复中间件,防止服务因未处理的异常而崩溃,并返回统一的 JSON 错误响应。
PanicRecovery
func PanicRecovery() gin.HandlerFunc实现:
func PanicRecovery() gin.HandlerFunc {
return gin.RecoveryWithWriter(io.Discard, func(c *gin.Context, recovered interface{}) {
// 1. 从上下文提取错误码
value, exists := c.Get(xCtx.ErrorCodeKey.String())
getErrMessage, msgExist := c.Get(xCtx.ErrorMessageKey.String())
// 2. 默认错误码: ServerInternalError (50000)
errorCode := xError.ServerInternalError
if exists && value != nil {
if ec, ok := value.(*xError.ErrorCode); ok && ec != nil {
errorCode = ec
}
}
// 3. 默认错误消息
if !msgExist {
getErrMessage = "未知错误,请稍后再试"
}
// 4. 记录日志
xLog.WithName(xLog.NamedMIDE).Error(c.Request.Context(), "Panic 恢复", ...)
// 5. 返回统一 JSON 响应
c.JSON(int(errorCode.Code/100), xBase.BaseResponse{...})
c.Abort()
})
}错误码提取
中间件会尝试从上下文获取错误信息:
字段
类型
响应格式
{
"context": "abc123-uuid",
"output": "SERVER_INTERNAL_ERROR",
"code": 50000,
"message": "服务器内部错误",
"error_message": "具体错误描述"
}响应字段说明
字段
类型
使用示例
基础使用
func main() {
router := gin.New()
router.Use(xHelper.RequestContext())
// 注册 Panic 恢复中间件
router.Use(xHelper.PanicRecovery())
router.Use(xHelper.HttpLogger())
router.Run(":8080")
}测试 Panic 恢复
func TestPanic(ctx *gin.Context) {
// 触发 Panic
panic("测试 Panic 恢复")
}响应:
{
"context": "550e8400-e29b-41d4-a716-446655440000",
"output": "SERVER_INTERNAL_ERROR",
"code": 50000,
"message": "服务器内部错误",
"error_message": "未知错误,请稍后再试"
}带错误码的 Panic
func GetUser(ctx *gin.Context) {
// 设置错误码后再 Panic
ctx.Set(xCtx.ErrorCodeKey.String(), xError.NotFound)
ctx.Set(xCtx.ErrorMessageKey.String(), "用户不存在")
panic("user not found")
}响应:
{
"context": "550e8400-e29b-41d4-a716-446655440000",
"output": "NOT_EXIST",
"code": 40004,
"message": "数据不存在",
"error_message": "用户不存在"
}日志输出
Panic 发生时会记录 ERROR 级别日志:
2024-01-15 10:30:00.123 [ERRO] [abc123] [MIDE] Panic 恢复
code=50000
output=SERVER_INTERNAL_ERROR
message=服务器内部错误
errorMessage=未知错误,请稍后再试
goroutine 1 [running]:
...工作流程
注意事项
中间件顺序
// PanicRecovery 应该在 HttpLogger 之前
router.Use(xHelper.RequestContext())
router.Use(xHelper.PanicRecovery()) // 先注册
router.Use(xHelper.HttpLogger()) // 后注册与 xError 配合
推荐使用 xError.NewError 而不是直接 Panic:
// 推荐:使用 xError
ctx.Error(xError.NewError(ctx.Request.Context(), xError.NotFound, "用户不存在", true))
return
// 不推荐:直接 Panic
panic("user not found")