duanbi2003 2018-01-12 11:01
浏览 85

更好的错误处理

Here https://github.com/astaxie/build-web-application-with-golang/blob/master/en/11.1.md described how to enhance error handling with custom router and custom error type according to http package.

type appError struct {
    Error   error
    Message string
    Code    int
}    

type appHandler func(http.ResponseWriter, *http.Request) *appError
// custom handler catching errors
func (fn appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    if e := fn(w, r); e != nil { // e is *appError, not os.Error.
        c := appengine.NewContext(r)
        c.Errorf("%v", e.Error)
        http.Error(w, e.Message, e.Code)
    }
}
// fetch data or return *appError
func viewRecord(w http.ResponseWriter, r *http.Request) *appError {
    c := appengine.NewContext(r)
    key := datastore.NewKey(c, "Record", r.FormValue("id"), 0, nil)
    record := new(Record)
    if err := datastore.Get(c, key, record); err != nil {
        return &appError{err, "Record not found", 404}
    }
    if err := viewTemplate.Execute(w, record); err != nil {
        return &appError{err, "Can't display record", 500}
    }
    return nil
}

The aim is to make all the handlers returning *appError in case of error and write it into response in the router, so there is no need to call c.JSON(500, err) directly in the code of viewRecord.

How to do the same with Gin?

  • 写回答

1条回答 默认 最新

  • doujubeng2942 2018-01-17 08:16
    关注

    Here @manucorporat gin-developer say:

    We encourage developers to use a middleware to handle the error responses, so they can split the error logic, from the normal flow logic.

    In the Gin to implement centralized error handling your should .Use(Middleware) and in the path handler's code use gin.Context.Error() to attach an error info to the request context. The Middleware is aware of gin.Context.Errors and here you can read them and process as you wish after gin.Context.Next().

    The code below.

    Error handling Gin Middleware:

    //
    // APP error definition
    //
    type appError struct {
        Code     int    `json:"code"`
        Message  string `json:"message"`
    }
    
    //
    // Middleware Error Handler in server package
    //
    func JSONAppErrorReporter() gin.HandlerFunc {
        return jsonAppErrorReporterT(gin.ErrorTypeAny)
    }
    
    func jsonAppErrorReporterT(errType gin.ErrorType) gin.HandlerFunc {
        return func(c *gin.Context) {
            c.Next()
            detectedErrors := c.Errors.ByType(errType)
    
            log.Println("Handle APP error")
            if len(detectedErrors) > 0 {
                err := detectedErrors[0].Err
                var parsedError *appError
                switch err.(type) {
                case *appError:
                    parsedError = err.(*appError )
                default:
                    parsedError = &appError{ 
                      code: http.StatusInternalServerError,
                      message: "Internal Server Error"
                    }
                }
                // Put the error into response
                c.IndentedJSON(parsedError.Code, parsedError)
                c.Abort()
                // or c.AbortWithStatusJSON(parsedError.Code, parsedError)
                return
            }
    
        }
    }
    
    //
    //  Report Error in app
    //
    func fetchSingleHostGroup(c *gin.Context) {
        hostgroupID := c.Param("id")
    
        hostGroupRes, err := getHostGroupResource(hostgroupID)
    
        if err != nil {
            // put the Error to gin.Context.Errors
            c.Error(err)
            return
        }
        // return data of OK
        c.JSON(http.StatusOK, *hostGroupRes)
    }
    //
    // Server setup
    //
    func main() {
        router := gin.Default()
        router.Use(JSONAppErrorReporter())
        router.GET("/hostgroups/:id", fetchSingleHostGroup)
        router.Run(":3000")
    }
    

    Another error handling ideas can be found in:

    评论

报告相同问题?

悬赏问题

  • ¥15 Vue3 大型图片数据拖动排序
  • ¥15 划分vlan后不通了
  • ¥15 GDI处理通道视频时总是带有白色锯齿
  • ¥20 用雷电模拟器安装百达屋apk一直闪退
  • ¥15 算能科技20240506咨询(拒绝大模型回答)
  • ¥15 自适应 AR 模型 参数估计Matlab程序
  • ¥100 角动量包络面如何用MATLAB绘制
  • ¥15 merge函数占用内存过大
  • ¥15 使用EMD去噪处理RML2016数据集时候的原理
  • ¥15 神经网络预测均方误差很小 但是图像上看着差别太大