1、在主入口新增
package mainimport ("flag""fmt""go/application/internal/config""go/application/internal/handler""go/application/internal/middleware""go/application/internal/svc"manage "go/pkg/manage""github.com/zeromicro/go-zero/core/conf""github.com/zeromicro/go-zero/rest""github.com/zeromicro/go-zero/rest/httpx")var configFile = flag.String("f", "etc/service-api.yaml", "配置文件")func main() {flag.Parse()var c config.Config// 读取配置文件中的值,将其保存在c变量上所以这一块传递的是地址conf.MustLoad(*configFile, &c)// 将全局配置保存在全局变量上config.GlobalConfig = c// 注册服务,传递服务配置server := rest.MustNewServer(c.RestConf)// 全局中间件这儿主要用来捕获一下全局的异常,抛出给前端server.Use(middleware.WithMiddleware)// 停止服务defer server.Stop()// 为上下文赋值将常用的方法绑定在上下文当中(redis、orm等等)ctx := svc.NewServiceContext(c)// 注册路由handler.RegisterHandlers(server, ctx)// 统一错误处理httpx.SetErrorHandler(manage.ErrHandler)fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)// 启动服务server.Start()}
通过server.Use(middleware.WithMiddleware) 来注册一个全局中间件,接受一个函数
2、中间件函数体
package middlewareimport ("fmt"manage "go/pkg/manage""net/http")func WithMiddleware(next http.HandlerFunc) http.HandlerFunc {return func(w http.ResponseWriter, r *http.Request) {defer func() {if err := recover(); err != nil {fmt.Println("============这儿是全局连接处理的异常===============")fmt.Println(err)fmt.Println("============这儿是全局连接处理的异常===============")manage.ResponseHandler(w, nil, &manage.ServerError)}}()next(w, r)}}
通过defer和recover来捕获全局异常,如果出现异常,给前端返回500、服务器内部错误,并输出错误信息
3、向前端返回错误信息函数
manage->response.go
package manageimport ("net/http""github.com/zeromicro/go-zero/rest/httpx")type Body struct {Codeint `json:"code"`Message string`json:"message"`Resultinterface{} `json:"data"`}// 统一返回入口,func ResponseHandler(w http.ResponseWriter, resp interface{}, err error) {if err != nil {httpx.OkJson(w, ErrHandler(err))// 如果err不为空的话,走错误处理函数,将err传递过去} else {// 没有错误信息,返回相应内容httpx.OkJson(w, Body{Code:OK.Code,Message: OK.Message,Result:resp,})}}
manage->errorResponse.go
package managetype CodeError struct {Codeint`json:"code"`Message string `json:"message"`}// 实现error的接口然后CodeError继承一下Error方法CodeError就为error类型的返回值func (e *CodeError) Error() string {return e.Message}// 返回给前端的数据func (e *CodeError) ErrorResponse() CodeError {return CodeError{Code:e.Code,Message: e.Message,}}// 用来自定义抛出的异常,支持调用传递func NewCodeError(code int, msg string) error {return &CodeError{Code:code,Message: msg,}}// 提供new方法,任意地方传递参数返回CodeError类型的数据func New(code int, msg string) CodeError {return CodeError{Code:code,Message: msg,}}// 默认异常状态码函数,只需传递错误信息即可,默认返回code-10001func DefaultErrHandler(message string) error {return &CodeError{Code:ServerError.Code,Message: message,}}// 自定义错误返回函数 错误函数主入口func ErrHandler(err error) interface{} {switch err.(type) {// 如果错误类型为CodeError,就返回错误类型的结构体case *CodeError:return errdefault:// 系统错误,500 错误提示return CodeError{Code: ServerError.Code, Message: err.Error()}}}
manage->status.go
package managevar (OK= New(0, "操作成功")ReidsError= New(6379, "redis连接失败")JwtError= New(500, "JWT解密失败")TokenError= New(401, "Token已过期")ServerError = New(500, "服务器内部错误"))
搞定收工