Skip to content

错误码配置 原创

在应用程序运行过程中,我们常常需要与客户端进行交互。交互一般分为两点:一个是返回正确响应下的结果集;另一个是返回错误响应下的错误码和消息体,以便告诉客户端,这一次请求发生了什么事,以及请求失败的原因。在错误码的处理上,又延伸出一个新的问题,那就是错误码的标准化处理。如果不对错误码进行提前预判,则会引发较大的麻烦。

因此,我们要尽可能地保证每个项目前后端的交互语言规则是一致的,也就是说,在搭建一个新项目之初,其中重要的一项预备工作就是将错误码格式标准化,以保证客户端可以“理解”错误码规则,不需要每次都写一套新的。

1、公共错误码

在项目目录 pkg/errorcode 下新建 common_code.go 文件,预定义项目中的一些公共错误码,以便引导和规范大家使用,如下:

go
package errorcode

// 公共错误代码
var (
	Success                   = NewError(0, "成功")
	ServerError               = NewError(100001, "服务内部错误")
	InvalidParams             = NewError(100002, "入参错误")
	NotFound                  = NewError(100003, "找不到")
	UnauthorizedAuthNotExist  = NewError(100004, "鉴权失败,找不到对应的AppKey和AppSecret")
	UnauthorizedTokenError    = NewError(100005, "鉴权失败,Token错误")
	UnauthorizedTokenTimeout  = NewError(100006, "鉴权失败,Token超时")
	UnauthorizedTokenGenerate = NewError(100007, "鉴权失败,Token生成失败")
	TooManyRequests           = NewError(100008, "请求太多")
	UserNotLogin              = NewError(100009, "用户未登录")
)

2、错误处理

在项目目录pkg/errorcode下新建errorcode.go文件,在其中编写常用的一些错误处理公共方法,用以标准化我们的错误输出,如下:

go
package errorcode

import (
	"fmt"
	"net/http"
)

type Error struct {
	code    int
	msg     string
	details []string
}

var codes = map[int]string{}

func NewError(code int, msg string) *Error {
	if _, ok := codes[code]; ok {
		panic(fmt.Sprintf("错误码%d已经存在,请更换一个", code))
	}
	codes[code] = msg
	return &Error{code: code, msg: msg}
}

func (e *Error) Error() string {
	return fmt.Sprintf("错误码: %d,错误信息: %s", e.Code(), e.Msg())
}

func (e *Error) Code() int {
	return e.code
}

func (e *Error) Msg() string {
	return e.msg
}

func (e *Error) Msgf(args []interface{}) string {
	return fmt.Sprintf(e.Msg(), args...)
}

func (e *Error) Details() []string {
	return e.details
}

func (e *Error) WithDetails(details ...string) *Error {
	newError := *e
	newError.details = []string{}

	newError.details = append(newError.details, details...)

	return &newError
}

func (e *Error) StatusCode() int {
	switch e.Code() {
	case Success.Code():
		return http.StatusOK
	case ServerError.Code():
		return http.StatusInternalServerError
	case InvalidParams.Code():
		return http.StatusBadRequest
	case NotFound.Code():
		return http.StatusNotFound
	case UnauthorizedAuthNotExist.Code():
		fallthrough
	case UnauthorizedTokenError.Code():
		fallthrough
	case UnauthorizedTokenGenerate.Code():
		fallthrough
	case UnauthorizedTokenTimeout.Code():
		return http.StatusUnauthorized
	case TooManyRequests.Code():
		return http.StatusTooManyRequests
	}
	return http.StatusInternalServerError
}

首先,在编写错误处理公共方法过程中,声明了 Error 结构体,用于表示错误的响应结果。然后,把 codes 作为全局错误码的存储载体,以便查看当前的注册情况。

最后,在调用 NewError 创建新的 Error 实例的同时,进行排重校验。

另外相对特殊的是 StatusCode 方法,它主要针对一些特定错误码进行状态码的转换。因为不同的内部错误码在 HTTP 状态码中表示不同的含义,所以我们需要将其区分开来,以便客户端及监控或报警等系统的识别和监听。

3、代码版本

本节开发完后,记得给代码标记,如下:

go
$ git add .
$ git commit -m "错误码配置"
最近更新