在gin中若是有錯誤須要響應給客戶端,若是每個都判斷,而且處理返回,若是項目複雜了,須要寫不少重複的代碼來響應錯誤,今天咱們來封裝一個統一處理錯誤包裝器,使用的是裝飾器模式。git
pkg/e/error.gogithub
package e import "github.com/gin-gonic/gin" //自定義api錯誤結構體 type ApiError struct { Status int `json:"-"` Code int `json:"code"` Message string `json:"message"` } func (err ApiError)Error() string { return err.Message }
pkg/e/error_wrapper.gojson
package e import ( "github.com/gin-gonic/gin" "net/http" ) type WrapperHandle func(c *gin.Context) (interface{}, error) func ErrorWrapper(handle WrapperHandle) gin.HandlerFunc { return func(c *gin.Context) { data, err := handle(c) if err != nil { apiError := err.(ApiError) c.JSON(apiError.Status, apiError) return } c.JSON(http.StatusOK, gin.H{"data": data}) } }
這裏的統一處理只是一個簡單的處理,介紹一種思路,具體的能夠根據項目進行改造
api/err_handle.goapi
package api import ( "cn.sockstack/gin_demo/pkg/e" "github.com/gin-gonic/gin" "net/http" ) func ErrorHandle(c *gin.Context) (interface{}, error) { query := c.Query("q") if query == "" { return nil, e.ApiError{ Status: http.StatusOK, //狀態碼 Code: 404, Message: "q的參數不能爲空", } } if query == "test" { return nil, e.ApiError{ Status: http.StatusOK, //狀態碼 Code: 404, Message: "q的參數不能爲test", } } return query, nil }
routers/test.goapp
package routers import ( "cn.sockstack/gin_demo/api" "cn.sockstack/gin_demo/pkg/e" "github.com/gin-gonic/gin" ) func test(r *gin.Engine) { //定義/test路由 r.GET("/test", api.Test) //響應json數據 r.GET("/json", api.Json) //響應xml數據 r.GET("/xml", api.Xml) //統一錯誤處理測試 r.GET("/error", e.ErrorWrapper(api.ErrorHandle)) }
{ "data": "hello" }
正常響應結果函數
{ "code": 404, "message": "q的參數不能爲test" }
{ "code": 404, "message": "q的參數不能爲空" }
能夠看到,兩次訪問都能處理錯誤結果,並以json返回,在業務開發中,只要返回自定義的ApiError錯誤,便可以統一格式返回錯誤。測試
這一節介紹的統一錯誤處理的靈感來源於gin的中間件。