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:
package main
import (
"fmt"
"github.com/gogf/gf/v2/errors/gerror"
)
func OpenFile() error {
return gerror.New("permission denied")
}
func OpenConfig() error {
return gerror.Wrap(OpenFile(), "configuration file opening failed")
}
func ReadConfig() error {
return gerror.Wrap(OpenConfig(), "reading configuration failed")
}
func main() {
fmt.Printf("%+v", ReadConfig())
}
Execution output example:
reading configuration failed: configuration file opening failed: permission denied
1. reading configuration failed
1). main.ReadConfig
/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/geg/errors/gerror/gerror2.go:18
2). main.main
/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/geg/errors/gerror/gerror2.go:25
2. configuration file opening failed
1). main.OpenConfig
/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/geg/errors/gerror/gerror2.go:14
2). main.ReadConfig
/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/geg/errors/gerror/gerror2.go:18
3). main.main
/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/geg/errors/gerror/gerror2.go:25
3. permission denied
1). main.OpenFile
/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/geg/errors/gerror/gerror2.go:10
2). main.OpenConfig
/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/geg/errors/gerror/gerror2.go:14
3). main.ReadConfig
/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/geg/errors/gerror/gerror2.go:18
4). main.main
/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/v2/geg/errors/gerror/gerror2.go:25
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 givenerror
interface object implements (contains) stack information. -
Format:
// HasStack checks and reports whether `err` implemented interface `gerror.IStack`.
HasStack(err error) bool -
Example:
func ExampleHasStack() {
err1 := errors.New("sql error")
err2 := gerror.New("write error")
fmt.Println(gerror.HasStack(err1))
fmt.Println(gerror.HasStack(err2))
// Output:
// false
// true
}
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 anerror
object, returning a stack list string. -
Format:
// Stack returns the stack callers as string.
// It returns the error string directly if the `err` does not support stacks.
Stack(err error) string -
Example:
func ExampleStack() {
var err error
err = errors.New("sql error")
err = gerror.Wrap(err, "adding failed")
err = gerror.Wrap(err, "api calling failed")
fmt.Println(gerror.Stack(err))
}Execution example output:
1. api calling failed
1). main.main
/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/.example/other/test.go:14
2. adding failed
1). main.main
/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/.example/other/test.go:13
3. sql error
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 theerror
interface object. -
Format:
// Current creates and returns the current level error.
// It returns nil if current level error is nil.
Current(err error) error -
Example:
func ExampleCurrent() {
var err error
err = errors.New("sql error")
err = gerror.Wrap(err, "adding failed")
err = gerror.Wrap(err, "api calling failed")
fmt.Println(err)
fmt.Println(gerror.Current(err))
// Output:
// api calling failed: adding failed: sql error
// api calling failed
}
Unwrap
Get the Next Level error
-
Description: The
Unwrap
method is used to get the next level errorerror
interface object. If the next level does not exist, it returnsnil
. -
Format:
// Unwrap returns the next level error.
// It returns nil if current level error or the next level error is nil.
Unwrap(err error) error -
Example 1: Simple error hierarchy access example.
func ExampleUnwrap() {
var err error
err = errors.New("sql error")
err = gerror.Wrap(err, "adding failed")
err = gerror.Wrap(err, "api calling failed")
fmt.Println(err)
err = gerror.Unwrap(err)
fmt.Println(err)
err = gerror.Unwrap(err)
fmt.Println(err)
// Output:
// api calling failed: adding failed: sql error
// adding failed: sql error
// sql error
} -
Example 2: Common iteration logic code example.
func IsGrpcErrorNotFound(err error) bool {
if err != nil {
for e := err; e != nil; e = gerror.Unwrap(e) {
if s, ok := status.FromError(e); ok && s != nil && s.Code() == codes.NotFound {
return true
}
}
}
return false
}
Cause
Get the Root Error error
-
Description: The
Cause
method allows us to obtain the root error information (original error) of theerror
object. -
Format:
// Cause returns the root cause error of `err`.
Cause(err error) error -
Example:
package main
import (
"fmt"
"github.com/gogf/gf/v2/errors/gerror"
)
func OpenFile() error {
return gerror.New("permission denied")
}
func OpenConfig() error {
return gerror.Wrap(OpenFile(), "configuration file opening failed")
}
func ReadConfig() error {
return gerror.Wrap(OpenConfig(), "reading configuration failed")
}
func main() {
fmt.Println(gerror.Cause(ReadConfig()))
}
// Output:
// permission denied