go-zero 全局异常处理-全局中间件

本文介绍了如何在Go-Zero框架中使用全局中间件捕获并处理异常,包括通过`server.Use(middleware.WithMiddleware)`注册中间件,以及使用`defer`和`recover`进行异常恢复,并通过自定义错误处理函数返回统一的错误响应。
摘要由CSDN通过智能技术生成

1、在主入口新增

package main

import (
	"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 middleware

import (
	"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 manage

import (
	"net/http"

	"github.com/zeromicro/go-zero/rest/httpx"
)

type Body struct {
	Code    int         `json:"code"`
	Message string      `json:"message"`
	Result  interface{} `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 manage

type CodeError struct {
	Code    int    `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-10001
func DefaultErrHandler(message string) error {
	return &CodeError{
		Code:    ServerError.Code,
		Message: message,
	}
}

// 自定义错误返回函数 错误函数主入口
func ErrHandler(err error) interface{} {
	switch err.(type) {
	// 如果错误类型为CodeError,就返回错误类型的结构体
	case *CodeError:
		return err
	default:
		// 系统错误,500 错误提示
		return CodeError{Code: ServerError.Code, Message: err.Error()}
	}
}

manage->status.go 

package manage

var (
	OK          = New(0, "操作成功")
	ReidsError  = New(6379, "redis连接失败")
	JwtError    = New(500, "JWT解密失败")
	TokenError  = New(401, "Token已过期")
	ServerError = New(500, "服务器内部错误")
)

搞定收工

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值