全书目录

第三十二篇:Gin 完全指南 —— 高速交警中枢宇宙

第十章:错误处理 —— 真正成熟的中枢,不会让每个窗口都各写各的事故报告

1 分钟 206 字 第 601 / 962 个阅读单元

初学时很多人每个 handler 都自己写一套错误返回:

go
if err != nil {
    c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
    return
}

不是不能写,但项目一大就会变成:

  • 格式不统一
  • 状态码策略不统一
  • 日志记录不统一
  • 调用栈埋点不统一

Gin 的一个好思路是:
handler 负责发现事故,中间件负责统一收口。

#1. 一个统一错误处理中间件
go
func ErrorHandler() gin.HandlerFunc {
    return func(c *gin.Context) {
        c.Next()

        if len(c.Errors) == 0 {
            return
        }
        if c.Writer.Written() {
            return
        }

        err := c.Errors.Last().Err
        c.JSON(http.StatusInternalServerError, gin.H{
            "success": false,
            "message": err.Error(),
        })
    }
}
#2. 业务 handler 里只上报错误
go
func getCheckpoint(c *gin.Context) {
    id := c.Param("id")

    if id != "A-17" {
        c.Error(errors.New("卡口不存在"))
        return
    }

    c.JSON(http.StatusOK, gin.H{
        "id":     id,
        "status": "online",
    })
}
#3. 这套机制的心智
text
窗口发现事故
   │
   ▼
把事故挂到 c.Errors
   │
   ▼
统一事故处理中心读取 c.Errors
   │
   ▼
按统一格式出事故回执

这套做法的价值在于:

  • 业务逻辑和错误包装解耦
  • 错误格式统一
  • 更容易接日志、告警、埋点