Gin 返回JSON数据 - refactor | Go 主题月

1,327 阅读2分钟

在上一遍 Gin 捕获异常中间件、封装返回自定义格式数据 | Go 主题月

通过 panic 方式 抛出异常,通过 recovery 方式进行捕获返回

在看到 Go-advice 发现原来 panic 方式不合理

不要(在生产环境)使用 panic()

显式处理错误

尽早返回,而不是使用深嵌套

开始调整

所以在原来基础之上对使用到 panic 方式进行调整

common.go 修改前

func Success(c *gin.Context, data interface{}) {
	c.JSON(http.StatusOK, gin.H{
		"code":    http.StatusOK,
		"data":    data,
		"message": "请求成功",
	})
}

common.go 修改后

func JSON(c *gin.Context, data interface{}) {
	c.JSON(http.StatusOK, data)
	c.Abort()
}

已注册接口为例

修改前

func (ac *AccountController) Register(c *gin.Context) {
	var registerInfo model.RegisterInfo
	if err := c.BindJSON(&registerInfo); err != nil {
		log.Println(err.Error())
		panic(api.ErrParam.WithErrMsg(err.Error()))
	}
	log.Printf("receiver param %s", registerInfo)
	accountService := service.AccountService{}
	accountService.Register(&registerInfo)
	common.Success(c, 1)
}

修改后

func (ac *AccountController) Register(c *gin.Context) {
	var registerInfo model.RegisterInfo
	if err := c.BindJSON(&registerInfo); err != nil {
		log.Println(err.Error())
		common.FailedParam(c)
		return
	}
	accountService := service.AccountService{}
	common.JSON(c, accountService.Register(&registerInfo))
}

注册逻辑调整

AccountService Register 方法调整,返回 api.JsonResult 格式

  • 在发生错误时,及时返回错误提示,使用 api.JsonResult 结构体封装
func (us *AccountService) Register(registerInfo *model.RegisterInfo) *api.JsonResult {
	log.Printf("receiver param %s", registerInfo)

	password := registerInfo.Password

	worker, err := util.NewWorker(16)
	if err != nil {
		log.Print(err)
		return api.JsonError(api.UserAddFailErr)
	}

	userDao := dao.UserDao{DbEngine: engine.GetOrmEngine()}
	exist, err := userDao.QueryByPhone(registerInfo.Phone)
	log.Printf("check Phone %v %v", exist, err)
	if exist || err != nil {
		return api.JsonError(api.PhoneExistErr)
	}

	exist, err = userDao.QueryByUserName(registerInfo.UserName)
	log.Printf("check UserName %v %v", exist, err)
	if exist || err != nil {
		return api.JsonError(api.UserNameExistErr)
	}

	// ....

	result, err := userDao.InsertUser(userInfo)
	log.Printf("add user result %v error %v", result, err)
	if err != nil {
		return api.JsonError(api.UserAddFailErr)
	}

	// ....
	
	result, err = userDao.InsertPassword(passwordInfo)
	log.Printf("add password result %v error %v", result, err)
	if err != nil {
		return api.JsonError(api.UserAddFailErr)
	}
	return api.JsonSuccess()
}

返回 JSON 结构数据

package api

type JsonResult struct {
	Code    int         `json:"code"`
	Message string      `json:"message"`
	Data    interface{} `json:"data"`
	Success bool        `json:"success"`
}

func Json(code int, message string, data interface{}, success bool) *JsonResult {
	return &JsonResult{
		Code:    code,
		Message: message,
		Data:    data,
		Success: success,
	}
}

func JsonData(data interface{}) *JsonResult {
	return &JsonResult{
		Code:    200,
		Data:    data,
		Success: true,
		Message: "请求成功",
	}
}

func JsonSuccess() *JsonResult {
	return &JsonResult{
		Code:    200,
		Data:    nil,
		Success: true,
		Message: "请求成功",
	}
}

func JsonError(err *CodeError) *JsonResult {
	return &JsonResult{
		Code:    err.Code,
		Message: err.Message,
		Data:    err.Data,
		Success: false,
	}
}

func (json *JsonResult) JsonWithMsg(message string) *JsonResult {
	json.Message = message
	return json
}

func (json *JsonResult) JsonWithCode(code int) *JsonResult {
	json.Code = code
	return json
}

func (json *JsonResult) JsonWithData(data interface{}) *JsonResult {
	json.Data = data
	return json
}

统一错误码

package api

import (
	"strconv"
)

var (
	OK = NewError(200, "请求成功")

	// 业务异常
	UserAddFailErr        = NewError(20001, "添加用户失败")

  // 其他更多 业务异常 ......
)

func NewError(code int, text string) *CodeError {
	return &CodeError{code, text, nil}
}

func NewErrorData(code int, text string, data interface{}) *CodeError {
	return &CodeError{code, text, data}
}

type CodeError struct {
	Code    int
	Message string
	Data    interface{}
}

func (e *CodeError) Error() string {
	return strconv.Itoa(e.Code) + ": " + e.Message
}

总结

去除原来 panic + recovery 方式返回错误,这样有点不可控

在程序发生 err 时,err != nil,判断错误,直接返回错误信息,不再往下执行,把状态变为可控

本次调整 git 记录可查看

gitee.com/shizidada/m…