Error Stack

The error implementation in the standard library is relatively simple and does not support stack tracing, which is not very user-friendly for the caller when an error occurs, as it cannot obtain detailed information about the error call chain. gerror supports error stack recording, and methods like New/Newf, Wrap/Wrapf, WrapSkip/WrapSkipf automatically record the stack information at the time the error occurs.

Example:

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/gogf/gf/v2/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. }

Execution output example:

  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/v2/geg/errors/gerror/gerror2.go:18
  5. 2). main.main
  6. /Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/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/v2/geg/errors/gerror/gerror2.go:14
  10. 2). main.ReadConfig
  11. /Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/geg/errors/gerror/gerror2.go:18
  12. 3). main.main
  13. /Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/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/v2/geg/errors/gerror/gerror2.go:10
  17. 2). main.OpenConfig
  18. /Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/geg/errors/gerror/gerror2.go:14
  19. 3). main.ReadConfig
  20. /Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/geg/errors/gerror/gerror2.go:18
  21. 4). main.main
  22. /Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/geg/errors/gerror/gerror2.go:25

Error Handling - Stack - 图1tip

The error stack path printed is the code path executed locally by the author.

As you can see, the caller can use the Wrap method to layer the underlying error information while including complete error stack information.

HasStack Determine Whether an Error Includes a Stack

  • Description: The HasStack method allows us to determine whether a given error interface object implements (contains) stack information.

  • Format:

    1. // HasStack checks and reports whether `err` implemented interface `gerror.IStack`.
    2. HasStack(err error) bool
  • Example:

    1. func ExampleHasStack() {
    2. err1 := errors.New("sql error")
    3. err2 := gerror.New("write error")
    4. fmt.Println(gerror.HasStack(err1))
    5. fmt.Println(gerror.HasStack(err2))
    6. // Output:
    7. // false
    8. // true
    9. }

Error Handling - Stack - 图2warning

Currently, this method is implemented by checking if the error object implements the gerror.IStack interface. If the error object does not implement this interface, it cannot determine if it includes stack information.

Stack Get Stack Information

  • Description: The Stack method allows us to obtain the complete stack information of an error object, returning a stack list string.

  • Format:

    1. // Stack returns the stack callers as string.
    2. // It returns the error string directly if the `err` does not support stacks.
    3. Stack(err error) string
  • Example:

    1. func ExampleStack() {
    2. var err error
    3. err = errors.New("sql error")
    4. err = gerror.Wrap(err, "adding failed")
    5. err = gerror.Wrap(err, "api calling failed")
    6. fmt.Println(gerror.Stack(err))
    7. }

    Execution example output:

    1. 1. api calling failed
    2. 1). main.main
    3. /Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/.example/other/test.go:14
    4. 2. adding failed
    5. 1). main.main
    6. /Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/.example/other/test.go:13
    7. 3. sql error

Error Handling - Stack - 图3warning

Currently, this method is implemented by retrieving the error object’s implementation of the gerror.IStack interface. If the error object does not implement this interface, this method will return an empty string.

Current Get the Current error

  • Description: The Current method is used to get the error information of the current level, returning through the error interface object.

  • Format:

    1. // Current creates and returns the current level error.
    2. // It returns nil if current level error is nil.
    3. Current(err error) error
  • Example:

    1. func ExampleCurrent() {
    2. var err error
    3. err = errors.New("sql error")
    4. err = gerror.Wrap(err, "adding failed")
    5. err = gerror.Wrap(err, "api calling failed")
    6. fmt.Println(err)
    7. fmt.Println(gerror.Current(err))
    8. // Output:
    9. // api calling failed: adding failed: sql error
    10. // api calling failed
    11. }

Unwrap Get the Next Level error

  • Description: The Unwrap method is used to get the next level error error interface object. If the next level does not exist, it returns nil.

  • Format:

    1. // Unwrap returns the next level error.
    2. // It returns nil if current level error or the next level error is nil.
    3. Unwrap(err error) error
  • Example 1: Simple error hierarchy access example.

    1. func ExampleUnwrap() {
    2. var err error
    3. err = errors.New("sql error")
    4. err = gerror.Wrap(err, "adding failed")
    5. err = gerror.Wrap(err, "api calling failed")
    6. fmt.Println(err)
    7. err = gerror.Unwrap(err)
    8. fmt.Println(err)
    9. err = gerror.Unwrap(err)
    10. fmt.Println(err)
    11. // Output:
    12. // api calling failed: adding failed: sql error
    13. // adding failed: sql error
    14. // sql error
    15. }
  • Example 2: Common iteration logic code example.

    1. func IsGrpcErrorNotFound(err error) bool {
    2. if err != nil {
    3. for e := err; e != nil; e = gerror.Unwrap(e) {
    4. if s, ok := status.FromError(e); ok && s != nil && s.Code() == codes.NotFound {
    5. return true
    6. }
    7. }
    8. }
    9. return false
    10. }

Cause Get the Root Error error

  • Description: The Cause method allows us to obtain the root error information (original error) of the error object.

  • Format:

    1. // Cause returns the root cause error of `err`.
    2. Cause(err error) error
  • Example:

    1. package main
    2. import (
    3. "fmt"
    4. "github.com/gogf/gf/v2/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. }
    18. // Output:
    19. // permission denied