错误堆栈
标准库的error错误实现比较简单,无法进行堆栈追溯,对于产生错误时的上层调用者来讲不是很友好,无法获得错误的调用链详细信息。gerror支持错误堆栈记录,通过New/Newf、Wrap/Wrapf、WrapSkip/WrapSkipf等方法均会自动记录当前错误产生时的堆栈信息。
示例:
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())
}执行后,输出示例:
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:::tip 其中打印的错误堆栈路径为笔者本地执行的代码路径。 :::
可以看到,调用端可以通过 Wrap 方法将底层的错误信息进行层级叠加,并且包含完整的错误堆栈信息。
HasStack 判断错误是否带堆栈
说明:通过
HasStack方法我们可以判断给定的error接口对象是否实现(包含)了堆栈信息。格式:
// HasStack checks and reports whether `err` implemented interface `gerror.IStack`. HasStack(err error) bool示例:
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 }
:::warning
目前该方法是通过判断错误对象是否实现gerror.IStack接口来实现的,如果错误对象未实现该接口那么将会无法识别其是否带有堆栈信息。
:::
Stack 获取堆栈信息
说明:通过
Stack方法我们可以获得error对象的完整堆栈信息,返回堆栈列表字符串。格式:
// Stack returns the stack callers as string. // It returns the error string directly if the `err` does not support stacks. Stack(err error) string示例:
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)) }执行后,输出示例信息:
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
:::warning
目前该方法是通过获取错误对象实现的gerror.IStack接口来实现的,如果错误对象未实现该接口那么该方法将会返回空字符串。
:::
Current 获取当前 error
说明:
Current方法用于获取当前层级的错误信息,通过error接口对象返回。格式:
// Current creates and returns the current level error. // It returns nil if current level error is nil. Current(err error) error示例:
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 获取下一层 error
说明:
Unwrap方法用于获取层级错误的下一级错误error接口对象。当下一层级不存在时,返回nil。格式:
// Unwrap returns the next level error. // It returns nil if current level error or the next level error is nil. Unwrap(err error) error示例1:简单的错误层级访问示例。
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 }示例2:常见遍历逻辑代码示例。
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 获取根错误 error
说明:通过
Cause方法我们可以获得error对象的根错误信息(原始错误)。格式:
// Cause returns the root cause error of `err`. Cause(err error) error示例:
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