Go语言实战 : API服务器 (5) 错误码 | 小册免费学

1.错误码定义

在errno包下定义,如下几个错误码

package errno

var(
	OK=&Errno{Code: 0,Message: "OK"}
	InternalServerError=&Errno{Code: 10001,Message: "Internal server error."}
	ErrBind=&Errno{Code: 10002,Message: "Error occurred while binding the request body to the struct."}
	ErrUserNotFound=&Errno{Code: 20102,Message: "The user was not found."}

)
复制代码
  • Code:用来标识一个错误,可以看作ID
  • Message: 用来显示具体的错误内容

2. 错误码设计

image.png
错误码分为三个部分

  • 服务级错误(1位):1代表系统内部错误,2代表用户非法操作造成的错误
  • 服务模块错误(2位):标识错误来自的服务模块
  • 具体错误码(2位): 具体的错误标识

3. 错误信息处理

1. 定义两个结构体Errno,Err,并实现error接口方法

type Errno struct {
	Code int
	Message string
}
type Err struct {
	Code int
	Message string
	Err error
}

func (err Errno)Error() string {//实现error接口方法
	return err.Message
}
func (err *Err) Error() string {//实现error接口方法
	return fmt.Sprintf("Err - code: %d, message: %s, error: %s", err.Code, err.Message, err.Err)
}
复制代码

2. 基于Errno结构体,去新建Err结构体

func New(errno *Errno,err error)  *Err{
	return &Err{Err: err,Code: errno.Code,Message: errno.Message}
}
复制代码

3. 定制Err结构体的message信息

func (err *Err) Add(message string)  error {
	err.Message+=" "+message
	return err
}
func (err *Err) Addf(format string,args ...interface{})  error{
	err.Message+=" "+fmt.Sprintf(format,args...)
	return err
}

复制代码

4. 对传入的error进行解析,解析出该出错的出错码和出错信息

func IsErrUserNotFound(err error) bool {
	decodeErr, _ := DecodeErr(err)
	return decodeErr==ErrUserNotFound.Code
}


func DecodeErr(err error)(int,string)  {
	if err != nil {
		return OK.Code,OK.Message
	}
	switch typed:=err.(type) {
	case *Err:
		return typed.Code,typed.Message
	case *Errno:
		return typed.Code,typed.Message
	default:
	}
	return InternalServerError.Code,err.Error()

}
复制代码

errno.go 完整代码如下

package errno

import "fmt"

type Errno struct {
	Code int
	Message string
}
type Err struct {
	Code int
	Message string
	Err error
}

func (err Errno)Error() string {//实现error接口方法
	return err.Message
}
func (err *Err) Error() string {//实现error接口方法
	return fmt.Sprintf("Err - code: %d, message: %s, error: %s", err.Code, err.Message, err.Err)
}

func New(errno *Errno,err error)  *Err{
	return &Err{Err: err,Code: errno.Code,Message: errno.Message}
}

func (err *Err) Add(message string)  error {
	err.Message+=" "+message
	return err
}
func (err *Err) Addf(format string,args ...interface{})  error{
	err.Message+=" "+fmt.Sprintf(format,args...)
	return err
}

func IsErrUserNotFound(err error) bool {
	decodeErr, _ := DecodeErr(err)
	return decodeErr==ErrUserNotFound.Code
}


func DecodeErr(err error)(int,string)  {
	if err != nil {
		return OK.Code,OK.Message
	}
	switch typed:=err.(type) {
	case *Err:
		return typed.Code,typed.Message
	case *Errno:
		return typed.Code,typed.Message
	default:
	}
	return InternalServerError.Code,err.Error()

}
复制代码

4. 错误码测试

1. 用一个结构体绑定从接收到的json字符串,并且判断是否出错

	var r struct{
		Username string `json:"username"`
		Password string `json:"password"`
	}
        var   err error
	if err:=c.Bind(&r); err!=nil{
		c.JSON(http.StatusOK,gin.H{"error":errno.ErrBind})
		return
	}
复制代码

2. 对产生的错误进行解析,生成错误码

	if r.Username==""{
		err=errno.New(errno.ErrUserNotFound,fmt.Errorf("username can not found in db: xx.xx.xx.xx")).Add("This is add message.")
		log.Printf("Get an error:%s",err)
		}
	if errno.IsErrUserNotFound(err){
		log.Printf("err type is ErrUserNotFound")
	}
	if r.Password==""{
		err=fmt.Errorf("password is empty")
	}
	code, message := errno.DecodeErr(err)
    c.JSON(http.StatusOK,gin.H{"code":code,",message":message})
    
    
复制代码

完整代码如下:

package user

import (
	"fmt"
	"log"
	"net/http"

	"goPro/pkg/errno"

	"github.com/gin-gonic/gin"
)

func Create(c *gin.Context)  {
	var r struct{
		Username string `json:"username"`
		Password string `json:"password"`
	}
	var   err error
	if err:=c.Bind(&r); err!=nil{
		c.JSON(http.StatusOK,gin.H{"error":errno.ErrBind})
		return
	}
	log.Printf("username is: [%s], password is [%s]", r.Username, r.Password)
	if r.Username==""{
		err=errno.New(errno.ErrUserNotFound,fmt.Errorf("username can not found in db: xx.xx.xx.xx")).Add("This is add message.")
		log.Printf("Get an error:%s",err)
		}
	if errno.IsErrUserNotFound(err){
		log.Printf("err type is ErrUserNotFound")
	}
	if r.Password==""{
		err=fmt.Errorf("password is empty")
	}
	code, message := errno.DecodeErr(err)
    c.JSON(http.StatusOK,gin.H{"code":code,",message":message})
}




复制代码

5. 样例测试

  • post请求不带json字符串

image.png

  • 只携带用户名

image.png

  • 只携带密码

image.png

  • 正常启动

image.png

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享