在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的中间件。