Golang web项目的全局错误处理
Echo framework写法示例
// 创建 Echo 实例
e := echo.New()
// Custom error handler
e.HTTPErrorHandler = func(err error, c echo.Context) {
// Log the error
log.Logger.Error("ErrorRequest: ", zap.Error(err))
// Prepare the error response
code := http.StatusInternalServerError
// he指针
var he *echo.HTTPError
// errors.As函数会尝试将err转为echo.HTTPError类型对象,若成功,则he即指向该对象
if errors.As(err, &he) {
// 将err转换为echo.HTTPError类成功后,将其Code字段值赋给上面声明的code变量(默认值500)
code = he.Code
// TODO 可以在此处对code值进行策略模式的处理
}
// Send the error response
if !c.Response().Committed {
if c.Request().Method == http.MethodHead {
// // 如果请求方法是HEAD,则发送一个没有内容的响应。
err = c.NoContent(code)
} else {
err = c.JSON(code, map[string]string{"error": err.Error()})
}
if err != nil {
log.Logger.Error("Failed to send error response: ", zap.Error(err))
}
}
}
Gin framework写法示例
func main() {
r := gin.New()
// 使用中间件来处理错误
r.Use(gin.RecoveryWithWriter(gin.DefaultErrorWriter))
// 注册全局错误处理中间件
r.Use(errorHandler)
// 依赖注入
helloHandler := utils.DIHelloHandler()
// ... 其他路由设置 ...
r.GET("/error", helloHandler.ErrorRequest)
// 运行Gin服务
r.Run(":8000")
}
// errorHandler 是一个中间件,用于捕获和处理错误
func errorHandler(c *gin.Context) {
c.Next()
if len(c.Errors) > 0 {
lastErr := c.Errors.Last()
// 如果 Meta 是 int(状态码)
if statusCode, ok := lastErr.Meta.(int); ok {
// TODO 可以在此处对code值进行策略模式的处理,记录日志,触发警告……等行为
c.AbortWithStatusJSON(statusCode, gin.H{
"error": lastErr.Error(),
})
return
}
// 没有状态码,默认 500
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
"error": lastErr.Error(),
})
}
}
func (h HelloHandler) ErrorRequest(context *gin.Context) {
_ = context.Error(fmt.Errorf("custom error")).SetType(gin.ErrorTypeAny).SetMeta(http.StatusTooManyRequests)
}