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, "服务器内部错误")
)
搞定收工