1. Error code definition

The following error codes are defined under the errno package

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."})Copy the code
  • Code: Identifies an error. This can be considered an ID
  • Message: Used to display specific error content

2. Error code design

The error code is divided into three parts

  • Service-level error (1 bit) : 1 indicates an internal system error, and 2 indicates an error caused by illegal user operations
  • Service module error (2 bits) : Identifies the service module from which the error came
  • Specific error code (2 bits) : Indicates a specific error identifier

3. Error message processing

1. Define two structures Errno and Err, and implement error interface methods

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

func (err Errno)Error(a) string {// Implement the error interface method
	return err.Message
}
func (err *Err) Error(a) string {// Implement the error interface method
	return fmt.Sprintf("Err - code: %d, message: %s, error: %s", err.Code, err.Message, err.Err)
}
Copy the code

2. Create an Err structure based on Errno

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

3. Customize the Message message of the Err structure

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
}

Copy the code

4. Parse the error message to find the error code and error information

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


func DecodeErr(err error)(int.string)  {
	iferr ! =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()

}
Copy the code

Errno. Go the complete code is as follows

package errno

import "fmt"

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

func (err Errno)Error(a) string {// Implement the error interface method
	return err.Message
}
func (err *Err) Error(a) string {// Implement the error interface method
	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)  {
	iferr ! =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()

}
Copy the code

4. Error code tests

1. Bind the RECEIVED JSON string with a structure and determine if there is an error

	var r struct{
		Username string `json:"username"`
		Password string `json:"password"`
	}
        var   err error
	iferr:=c.Bind(&r); err! =nil{
		c.JSON(http.StatusOK,gin.H{"error":errno.ErrBind})
		return
	}
Copy the code

2. Parse the error and generate an error code

	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})
    
    
Copy the code

The complete code is as follows:

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
	iferr:=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})
}




Copy the code

5. Sample test

  • The POST request does not contain a JSON string

  • Carry only the user name

  • Carry only your password

  • Normal boot