37DATA

GoFrame错误处理

背景

Go服务接口报错,接口返回只有一行错误信息,没有具体的堆栈信息和告警,不方便排除错误

Go Error

Go 中的每一个错误都需要处理。错误应该明确地当成业务的一部分,任何可以预见的问题都需要做错误处理。

Go 语言中,Go Error 是一个接口。实现、创建或抛出错误,实际上就是实现这个接口。
http://golang.org/pkg/builtin/#error

// The error built-in interface type is the conventional interface for// representing an error condition, with the nil value representing no error.type error interface {  Error() string}

Go Error 缺少上下文信息,一般会使用第三方的错误库(github.com/pkg/errors),把一些执行的上下文加入,将错误包装在另一个错误中,同时保留原始内容。使用 New 函数生成的错误,自带调用堆栈信息。

// 新生成一个错误, 带堆栈信息func New(message string) error// 只附加新的信息func WithMessage(err error, message string) error// 只附加调用堆栈信息func WithStack(err error) error// 同时附加堆栈和信息func Wrapf(err error, format string, args ...interface{}) error// 获得最根本的错误原因func Cause(err error) error例子:_, err := ioutil.ReadAll(r)if err != nil {  return errors.Wrap(err, "read failed")}

GoFrame的错误处理

  • 错误处理组件

  • 全错误堆栈设计

  • web服务异常处理

Image

在业务处理返回错误信息,使用gerror错误组件返回错误信息

gerror.New("错误信息")

使用内置错误码返回
https://github.com/gogf/gf/blob/master/errors/gcode/gcode.go
gerror.NewCode(gcode.CodeInternalError, "错误信息")

使用指定错误码返回
gerror.NewCode(gcode.New(10000, "", nil), "错误信息")

异常错误中间件


GoFrame HTTP执行流程中产生panic异常时,默认处理是记录到Serve的日志文件中。支持通过注册中间件方式手动捕获,然后自定义相关的错误处理。
GoFrame在中间件提供r.GetError()的方法获取错误的信息,支持通过%+v打印详细的堆栈信息。

func HandlerError(r *ghttp.Request) {    r.Middleware.Next()    if err := r.GetError(); err != nil {        wlog.New().Errorf(r.GetCtx(), "%+v", err)    }}

把错误处理的中间件引入使用,可以实现框架的统一错误处理

apiServer.Group("/", func(group *ghttp.RouterGroup) {    group.Middleware(        w.Middleware(ctx).HandlerError,        ghttp.MiddlewareHandlerResponse,    )    router.BindController(group)})

1、日志打印错误和堆栈信息

2、Error级别日志触发告警通知