In Gin again catch exceptions middleware, encapsulation return custom formatting data | Go on topic

Exceptions are thrown in Panic mode and captured and returned in recovery mode

After seeing go-advice, I found that the panic method is unreasonable

Don’t use Panic (in production)

Explicit handling error

Return early rather than using deep nesting

Began to adjust

Therefore, on the basis of the original use of panic mode to adjust

Common. Before go to modify

func Success(c *gin.Context, data interface{}) {
	c.JSON(http.StatusOK, gin.H{
		"code":    http.StatusOK,
		"data":    data,
		"message": "Request successful"})},Copy the code

Common. Go after modification

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

The registered interface is used as an example

Before the change

func (ac *AccountController) Register(c *gin.Context) {
	var registerInfo model.RegisterInfo
	iferr := 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)}Copy the code

The modified

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

Copy the code

Registration logic adjustment

The AccountService Register method is adjusted to return the api.jsonResult format

  • In the event of an error, an error message is returned, encapsulated by the api.jsonResult structure
func (us *AccountService) Register(registerInfo *model.RegisterInfo) *api.JsonResult {
	log.Printf("receiver param %s", registerInfo)

	password := registerInfo.Password

	worker, err := util.NewWorker(16)
	iferr ! =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)
	ifexist || err ! =nil {
		return api.JsonError(api.PhoneExistErr)
	}

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

	/ /...

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

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

Returns JSON structured data

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: "Request successful",}}func JsonSuccess(a) *JsonResult {
	return &JsonResult{
		Code:    200,
		Data:    nil,
		Success: true,
		Message: "Request successful",}}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
}
Copy the code

Unified error code

package api

import (
	"strconv"
)

var (
	OK = NewError(200."Request successful")

	// The service is abnormal
	UserAddFailErr        = NewError(20001."Failed to add user")

  // Other service exceptions......
)

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(a) string {
	return strconv.Itoa(e.Code) + ":" + e.Message
}
Copy the code

conclusion

Remove the original panic + recovery return error, which is a little uncontrollable

When an ERR occurs in the program, err! = nil, error, return error message, don’t go down, make the state controllable

You can view the git record of this adjustment

Gitee.com/shizidada/m…