Gin错误处理中间件示例

参考示例:

 // getValidatorErrMsg 获得友好的validator错误信息
func getValidatorErrMsg(fieldErr validator.FieldError) string {
    switch fieldErr.Tag() {
    case "required":
        return fmt.Sprintf("%s 是必填字段", fieldErr.Field())
    case "min":
        return fmt.Sprintf("%s 最小长度为 %s", fieldErr.Field(), fieldErr.Param())
    case "max":
        return fmt.Sprintf("%s 最大长度为 %s", fieldErr.Field(), fieldErr.Param())
    case "email":
        return fmt.Sprintf("%s 必须是有效的电子邮件地址", fieldErr.Field())
    case "eqfield":
        return fmt.Sprintf("%s 必须与 %s 相同", fieldErr.Field(), fieldErr.Param())
    case "gt":
        return fmt.Sprintf("%s 必须大于 %s", fieldErr.Field(), fieldErr.Param())
    case "gte":
        return fmt.Sprintf("%s 必须大于等于 %s", fieldErr.Field(), fieldErr.Param())
    case "lt":
        return fmt.Sprintf("%s 必须小于 %s", fieldErr.Field(), fieldErr.Param())
    case "lte":
        return fmt.Sprintf("%s 必须小于等于 %s", fieldErr.Field(), fieldErr.Param())
    case "eq":
        return fmt.Sprintf("%s 必须等于 %s", fieldErr.Field(), fieldErr.Param())
    case "len":
        return fmt.Sprintf("%s 长度必须等于 %s", fieldErr.Field(), fieldErr.Param())
    default:
        return fmt.Sprintf("%s 验证失败 (%s)", fieldErr.Field(), fieldErr.Tag())
    }
}


// ServerErrorHandleMiddleware 错误处理中间件,处理后续中间件或路由的错误,需放到最前面
func ServerErrorHandleMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        // 先进入后续路由/中间件
        c.Next()

        if len(c.Errors) == 0 {
            // 无错误
            return
        }
        if len(c.Errors) > 1 {
            // 存在多个错误,判定为错误处理不合规
            // 整个请求过程中,触发错误应该立即结束并返回
            c.JSON(http.StatusInternalServerError, gin.H{
                "detail": "错误处理不合规",
            })
            return
        }
        // 开始包装错误
        finalErr := c.Errors[0]
        msgSlice := make([]string, 0)
        var finalCode int
        if validatorErrs, ok := finalErr.Err.(validator.ValidationErrors); ok {
            // 返回的是validator触发的错误
            // validator会把错误收集在[]FieldError中
            // 收集错误文本信息
            for _, err := range validatorErrs {
                msg := getValidatorErrMsg(err)
                msgSlice = append(msgSlice, msg)
            }
            // 设定错误状态码
            finalCode = http.StatusBadRequest

        } else if mError, ok := merror.IsMError(finalErr.Err); ok {
            // 返回的是自定义错误
            msg := mError.Detail
            msgSlice = append(msgSlice, msg)
            finalCode = mError.Code
        } else {
            // 其他错误
            msgSlice = append(msgSlice, "未正确处理错误")
            finalCode = http.StatusInternalServerError
        }
        // 拼接错误文本
        detail := strings.Join(msgSlice, " | ")
        c.JSON(finalCode, gin.H{
            "detail": detail,
        })
        return
    }
}

 

posted @ 2025-07-11 10:44  CJTARRR  阅读(21)  评论(0)    收藏  举报