beego v2 处理全局异常
beego v2与v1有很大的变更,最近我在自己写一个小项目玩,由于不太会前端代码,所以选择使用beego框架,毕竟他有着支持web的小优势。当然,与前端后分离的没办法比,也与go-admin这类的不一样。但有个好处,就是可以自己随意定制前端界面。
但我在使用的时候,准备写一个全局异常捕获的时候,碰到问题了。通常这种情况,我第一个想到的是使用中间件。但我用网上搜了好几次,用AI也生成过,也看了下官方提供的例子,发现都没办法实现全局异常捕获。,v2版本与gin这类不一样,他没有Next函数(当然也可能是我没有找到),后面我跟踪了中间件的源代码,他是多次调用中件间,没办法直接在中间件上使用defer fun()进行全局异常捕获。
后面经过我多次跟踪查看,发现他配置文件BConfig有一个属性
// RecoverFunc// @Description when Beego want to recover from panic, it will use this func as callback// see RecoverPanic// @Default defaultRecoverPanicRecoverFunc func(*context.Context, *Config)
但这个又比较坑,一个是没有对外开放的函数,一个是他直接使用了自己默认的处理
res.RecoverFunc = defaultRecoverPanic
我这个项目本来就是一个玩一玩的小项目,想做个全局异常捕获,但又不想写太多日志处理。后面我灵机一想,想到一个好办法。以下是我实现的代码,可以参考一下。
新增一个异常处理函数
var oldFunc func(*context.Context, *web.Config)func HandleRecover(cfg *web.Config) {oldFunc = cfg.RecoverFunccfg.RecoverFunc = RecoverFunc
}func RecoverFunc(ctx *context.Context, cfg *web.Config) {if err := recover(); err != nil {if e, ok := err.(bresp.PageError); ok {if e.Code != 200 {ctx.Output.SetStatus(e.Code)ctx.WriteString(e.Message)} else {ctx.Output.SetStatus(e.Code)ctx.JSONResp(bresp.RespMessage(e.Message))}return}if oldFunc != nil {oldFunc(ctx, cfg)}}
}
这个可以对我们自定义的异常进行解析,确保已知的错误,都能正常返回200,同时对非已知道的异常不需要做太多的日志处理,直接使用他默认的方法。
只要在main.go里使用以下代码,即可实现
middleware.HandleRecover(beego.BConfig)
这样一样,我们在逻辑处理时,只要判断有err时,就直接 panic(PageError{})即可
func Dangerous(v interface{}, code ...int) {if v == nil {return}c := 200if len(code) > 0 {c = code[0]}switch t := v.(type) {case string:if t != "" {panic(PageError{Code: c, Message: t})}case error:panic(PageError{Code: c, Message: t.Error()})}
}
这样,只要有返回err,我们就直接调用 Dangerous函数,即可,不需要一直if err != nil {}.
这样可以省掉很多错误判断和错误处理。
希望对大家有帮助~
另,如果有自己做日志处理的,或是想自己写异常日志的话,可以不需要使用oldFunc,自己去实现,可以参考自带的defaultRecoverPanic函数