自定义业务错误信息
在实际开发中引入错误码有如下好处:
Go 中的 HTTP 服务器开发都是引用 net/http
包,该包中只有 60 个错误码,基本都是跟 HTTP 请求相关的。在大型系统中,这些错误码完全不够用,而且跟业务没有任何关联,满足不了业务需求。
在实际开发中,一个错误类型通常包含两部分:Code 部分,用来唯一标识一个错误;Message 部分,用来展示错误信息,这部分错误信息通常供前端直接展示。
一个良好结构的错误码有助于简化问题描述, 当前设计的错误码共有五位, 结构如下:
1 | 00 | 01 |
---|---|---|
服务级错误 | 服务模块 | 具体错误代码 |
在项目目录下新建一个 apicommon 目录, 并创建相应的模块。
package apicommon
import (
"github.com/gin-gonic/gin"
"net/http"
)
type Response struct {
Error *Error `json:"error,omitempty"`
Msg string `json:"message"`
Code int64 `json:"code"`
Data interface{} `json:"result,omitempty"`
}
type Error struct {
Code int64 `json:"code"` // 错误码
Msg string `json:"message"` // 返回给用户的信息
Data string `json:"data,omitempty"` // 保存的内部错误信息
}
// ReturnErrorResponse 返回错误
func ReturnErrorResponse(ctx *gin.Context, errmsg string, code int64, err string) {
response := &Response{
Error: &Error{
Msg: errmsg,
Code: code,
Data: err,
},
}
ctx.JSON(http.StatusOK, response)
return
}
上面介绍了错误码的一些知识,这一部分讲开发中是如何使用 自定义错误函数来处理错误信息的。为了演示,我们新增一个根据手机号获取验证码的 API:
handler/router.go 中添加路由
func RouterStart() {
gin.SetMode(gin.ReleaseMode) //设置gin模式
router := gin.New()
personal := router.Group("/api/v2")
{
personal.POST("/sso/getAuthCode", handler.GetAuthCode)
}
logger.Info("API server start", "listen", config.Conf.Console.Port)
router.Run(config.Conf.Console.Port)
}
handler 目录下增加业务处理函数 handler/personal.go
//手机号校验
func VerifyMobileFormat(mobileNum string) bool {
regular := "^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|166|198|199|(147))\\d{8}$"
reg := regexp.MustCompile(regular)
return reg.MatchString(mobileNum)
}
// 根据手机号获取验证码
func GetAuthCode(ctx *gin.Context) {
phone := ctx.PostForm("telephone")
logger.Info("GetAuthCodeRequest req:", "phone:", phone)
//判断手机号是否正确
res := VerifyMobileFormat(phone)
if res == false { //如果错误,则返回:手机号错误信息
apicommon.ReturnErrorResponse(ctx, "手机号错误!", -1, "Wrong phone number")
} else { //如果正确,则发送验证码给用户,并将验证码set到redis中
//生成6位数随机验证码
auth_code := fmt.Sprintf("%06v", rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(1000000))
//调用短信服务商,发送短信,此处代码暂时省略
fmt.Println(auth_code)
//将手机号及验证码set到redis中,过期时间为30s
redis.RedisDB.Set(phone, auth_code, 30*time.Second)
apicommon.ReturnSuccessResponse(ct "success", 0, nil)
}
}
经过编译及运行以上代码后,进行测试和验证
# curl --location --request POST 'localhost:9100/api/v2/sso/getAuthCode' \
--form 'telephone="11081719844"'
{
"message": "手机号错误!",
"code": -1,
"result": "Wrong phone number"
}
因为传入的手机号码错误,所以报错:手机号错误
# curl --location --request POST 'localhost:9100/api/v2/sso/getAuthCode' \
--form 'telephone="18281981546"'
{
"message": "success",
"code": 0,
"result": "nil"
}
如果验证手机号码通过,则会返回成功的 message: success和code: 0 和result: nil。
如果 API 是对外的,错误信息数量有限,则制定错误码非常容易,强烈建议使用错误码。如果是内部系统,特别是庞大的系统,内部错误会非常多,这时候没必要为每一个错误制定错误码,而只需为常见的错误制定错误码,对于普通的错误,系统在处理时会统一作为 InternalServerError 处理。
本系列文章: 从零开发区块链应用(一)--golang配置文件管理工具viper 从零开发区块链应用(二)--mysql安装及数据库表的安装创建 从零开发区块链应用(三)--mysql初始化及gorm框架使用 从零开发区块链应用(四)--自定义业务错误信息 从零开发区块链应用(五)--golang网络请求 从零开发区块链应用(六)--gin框架使用 从零开发区块链应用(七)--gin框架参数获取 从零开发区块链应用(八)--结构体初识 从零开发区块链应用(九)--区块链结构体创建 从零开发区块链应用(十)--golang协程使用 从零开发区块链应用(十一)--以太坊地址生成 从零开发区块链应用(十二)--以太坊余额查询 从零开发区块链应用(十三)--以太坊区块查询 从零开发区块链应用(十四)--以太坊交易哈希查询 从零开发区块链应用(十五)--以太坊交易匹配查询 从零开发区块链应用(十六)--ETH转账处理
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!