gerror

gerror模块提供了更丰富的错误处理功能。

使用方式

  1. import "github.com/gogf/gf/errors/gerror"

接口文档

https://godoc.org/github.com/gogf/gf/errors/gerror

  1. func New(value interface{}) error
  2. func NewText(text string) error
  3. func Cause(err error) error
  4. func Stack(err error) string
  5. func Wrap(err error, text string) error
  6. func Wrapf(err error, format string, args ...interface{}) error
  7. type Error
  8. func (err *Error) Cause() error
  9. func (err *Error) Error() string
  10. func (err *Error) Format(s fmt.State, verb rune)
  11. func (err *Error) Stack() string

错误堆栈

标准库的error错误实现比较简单,无法进行堆栈追溯,对于产生错误时的上层调用者来讲不是很友好,无法获得错误的调用链详细信息。gerror支持错误堆栈记录,通过New*/Wrap*均会自动记录当前错误产生时的堆栈信息。

使用示例:

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/gogf/gf/errors/gerror"
  5. )
  6. func OpenFile() error {
  7. return gerror.New("permission denied")
  8. }
  9. func OpenConfig() error {
  10. return gerror.Wrap(OpenFile(), "configuration file opening failed")
  11. }
  12. func ReadConfig() error {
  13. return gerror.Wrap(OpenConfig(), "reading configuration failed")
  14. }
  15. func main() {
  16. fmt.Printf("%+v", ReadConfig())
  17. }

执行后,终端输出:

  1. reading configuration failed: configuration file opening failed: permission denied
  2. 1. reading configuration failed
  3. 1). main.ReadConfig
  4. /Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/geg/errors/gerror/gerror2.go:18
  5. 2). main.main
  6. /Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/geg/errors/gerror/gerror2.go:25
  7. 2. configuration file opening failed
  8. 1). main.OpenConfig
  9. /Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/geg/errors/gerror/gerror2.go:14
  10. 2). main.ReadConfig
  11. /Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/geg/errors/gerror/gerror2.go:18
  12. 3). main.main
  13. /Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/geg/errors/gerror/gerror2.go:25
  14. 3. permission denied
  15. 1). main.OpenFile
  16. /Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/geg/errors/gerror/gerror2.go:10
  17. 2). main.OpenConfig
  18. /Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/geg/errors/gerror/gerror2.go:14
  19. 3). main.ReadConfig
  20. /Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/geg/errors/gerror/gerror2.go:18
  21. 4). main.main
  22. /Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/geg/errors/gerror/gerror2.go:25

可以看到,调用端可以通过Wrap方法将底层的错误信息进行层级叠加,并且包含完整的错误堆栈信息。

fmt格式化

通过以上示例我们可以看到,通过%+v的打印格式可以打印出完整的堆栈信息,当然gerror.Error对象支持多种fmt格式:

格式符 输出内容
%v, %s 打印所有的层级错误信息,构成完成的字符串返回,多个层级使用:拼接。
%-v, %-s 打印当前层级的错误信息,返回字符串。
%+s 打印完整的堆栈信息列表。
%+v 打印所有的层级错误信息字符串,以及完整的堆栈信息,等同于%s\n%+s

使用示例:

  1. package main
  2. import (
  3. "errors"
  4. "fmt"
  5. "github.com/gogf/gf/errors/gerror"
  6. )
  7. func Error1() error {
  8. return errors.New("test1")
  9. }
  10. func Error2() error {
  11. return gerror.New("test2")
  12. }
  13. func main() {
  14. err1 := Error1()
  15. err2 := Error2()
  16. fmt.Printf("%s, %-s, %+s\n", err1, err1, err1)
  17. fmt.Printf("%v, %-v, %+v\n", err1, err1, err1)
  18. fmt.Printf("%s, %-s, %+s\n", err2, err2, err2)
  19. fmt.Printf("%v, %-v, %+v\n", err2, err2, err2)
  20. }

执行后,终端输出为:

  1. test1, test1, test1
  2. test1, test1, test1
  3. test2, test2, 1. test2
  4. 1). main.Error2
  5. /Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/geg/errors/gerror/gerror1.go:15
  6. 2). main.main
  7. /Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/geg/errors/gerror/gerror1.go:20
  8. test2, test2, test2
  9. 1. test2
  10. 1). main.Error2
  11. /Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/geg/errors/gerror/gerror1.go:15
  12. 2). main.main
  13. /Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/geg/errors/gerror/gerror1.go:20

Stack方法

  1. func Stack(err error) string

通过Stack方法我们可以获得error对象的完整堆栈信息,返回堆栈列表字符串。注意参数为标准库error类型,当该参数为gerror模块生成的error时,或者开发者自定义的error对象实现了gerror.ApiStack接口时支持打印,否则,返回空字符串。

使用示例:

  1. package main
  2. import (
  3. "errors"
  4. "fmt"
  5. "github.com/gogf/gf/errors/gerror"
  6. )
  7. func Error1() error {
  8. return errors.New("test1")
  9. }
  10. func Error2() error {
  11. return gerror.New("test2")
  12. }
  13. func main() {
  14. err1 := Error1()
  15. err2 := Error2()
  16. fmt.Println("err1:", gerror.Stack(err1))
  17. fmt.Println("err2:", gerror.Stack(err2))
  18. }

执行后,终端输出:

  1. err1:
  2. err2:
  3. 1. test2
  4. 1). main.Error2
  5. /Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/geg/errors/gerror/gerror3.go:15
  6. 2). main.main
  7. /Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/geg/errors/gerror/gerror3.go:20

Cause方法

  1. func Cause(err error) error

通过Cause方法我们可以获得error对象的根错误信息(原始错误)。注意参数为标准库error类型,当该参数为gerror模块生成的error时,或者开发者自定义的error对象实现了gerror.ApiCause接口时支持打印,否则,返回输出的error对象。

使用示例:

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/gogf/gf/errors/gerror"
  5. )
  6. func OpenFile() error {
  7. return gerror.New("permission denied")
  8. }
  9. func OpenConfig() error {
  10. return gerror.Wrap(OpenFile(), "configuration file opening failed")
  11. }
  12. func ReadConfig() error {
  13. return gerror.Wrap(OpenConfig(), "reading configuration failed")
  14. }
  15. func main() {
  16. fmt.Println(gerror.Cause(ReadConfig()))
  17. }

执行后,终端输出:

  1. permission denied

日志输出支持

glog日志管理模块天然支持对gerror错误堆栈打印支持,这种支持不是强耦合性的,而是通过fmt格式化打印接口支持的。

使用示例:

  1. package main
  2. import (
  3. "errors"
  4. "github.com/gogf/gf/os/glog"
  5. "github.com/gogf/gf/errors/gerror"
  6. )
  7. func Error1() error {
  8. return errors.New("test1")
  9. }
  10. func Error2() error {
  11. return gerror.New("test2")
  12. }
  13. func main() {
  14. glog.Println(Error1())
  15. glog.Println(Error2())
  16. }

执行后,终端输出:

  1. 2019-07-13 15:01:31.131 test1
  2. 2019-07-13 15:01:31.131 test2
  3. 1. test2
  4. 1). main.Error2
  5. /Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/geg/errors/gerror/gerror5.go:16
  6. 2). main.main
  7. /Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/geg/errors/gerror/gerror5.go:21