我们在使用Gin框架时,可能在handler中有很多分支判断语句,就要写很多的ctx.Json来返回数据,这样用起来很麻烦,看起来也不美观。本文将使用一个适配器来简化Gin的数据响应。
比如,我们在使用Gin框架时,往往会这么写,在创建用户的handler中反复使用ctx.Json来返回数据,handler多了也会显得很烦。因此能不能实现一个handle,直接返回值就可以达到写出数据的目的呢。这时就可以使用适配器模式来进行优化一下了。
type User struct {
Username string `json:"username"`
Password string `json:"password"`
Email string `json:"email"`
PhoneNum string `json:"phoneNum"`
}
type Response struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data"`
}
func CreateUser(ctx *gin.Context) {
var u User
err := ctx.Bind(&u)
if err != nil {
ctx.Status(http.StatusBadRequest)
return
}
// 查询数据库
err = userService.AddUser(&u)
if err != nil {
ctx.JSON(http.StatusOK, &Response{
Code: 1,
Message: "Create user failed",
Data: nil,
})
return
}
ctx.JSON(http.StatusOK, &Response{
Code: 0,
Message: "Create user success",
Data: nil,
})
}
优化后的代码:
首先我们定义一个通用的Response
package response
type resResult struct {
Data []interface{} `json:"data"`
Status uint32 `json:"status"`
Message string `json:"message"`
}
type Response struct {
HttpStatus int
R resResult
}
// 为了提高效率我们可以使用一个Pool
var pool = sync.Pool{
New: func() interface{} {
return &Response{}
},
}
// 定义自己的返回code
const (
QuerySuccess uint32 = iota
QueryFailed
)
var MessageForCode = map[uint32]string{
QuerySuccess: "查询成功",
QueryFailed: "查询失败",
}
func NewResponse(status int, code uint32, data ...interface{}) *Response {
response := pool.Get().(*Response)
response.HttpStatus = status
response.R.Status = code
response.R.Message = MessageForCode[code]
response.R.Data = data
if len(data) == 0 {
response.R.Data = make([]interface{}, 0)
} else {
response.R.Data = data
}
return response
}
func PutResponse(res *Response) {
pool.Put(res)
}
func NewResponseOk(code uint32, data ...interface{}) *Response {
return NewResponse(http.StatusOK, code, data...)
}
然后定义一个适配器:
type Handler func(ctx *gin.Context) *serialize.Response
func HandlerAdapter(h Handler) gin.HandlerFunc {
return func(ctx *gin.Context) {
r := h(ctx)
if r != nil {
ctx.JSON(r.HttpStatus, &r.R)
}
serialize.PutResponse(r)
}
}
然后就可以使用自己的handler来处理请求了:
上面的看起来是不是舒服多了。
注册handler时:
func Register(engine *gin.Engine) {
engine.Post("/api/user", HandlerAdapter(controller.CreateUser))
}