github.com/wangyougui/gf/v2@v2.6.5/errors/gerror/gerror_api_stack.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/wangyougui/gf. 6 7 package gerror 8 9 import ( 10 "runtime" 11 ) 12 13 // stack represents a stack of program counters. 14 type stack []uintptr 15 16 const ( 17 // maxStackDepth marks the max stack depth for error back traces. 18 maxStackDepth = 64 19 ) 20 21 // Cause returns the root cause error of `err`. 22 func Cause(err error) error { 23 if err == nil { 24 return nil 25 } 26 if e, ok := err.(ICause); ok { 27 return e.Cause() 28 } 29 if e, ok := err.(IUnwrap); ok { 30 return Cause(e.Unwrap()) 31 } 32 return err 33 } 34 35 // Stack returns the stack callers as string. 36 // It returns the error string directly if the `err` does not support stacks. 37 func Stack(err error) string { 38 if err == nil { 39 return "" 40 } 41 if e, ok := err.(IStack); ok { 42 return e.Stack() 43 } 44 return err.Error() 45 } 46 47 // Current creates and returns the current level error. 48 // It returns nil if current level error is nil. 49 func Current(err error) error { 50 if err == nil { 51 return nil 52 } 53 if e, ok := err.(ICurrent); ok { 54 return e.Current() 55 } 56 return err 57 } 58 59 // Unwrap returns the next level error. 60 // It returns nil if current level error or the next level error is nil. 61 func Unwrap(err error) error { 62 if err == nil { 63 return nil 64 } 65 if e, ok := err.(IUnwrap); ok { 66 return e.Unwrap() 67 } 68 return nil 69 } 70 71 // HasStack checks and reports whether `err` implemented interface `gerror.IStack`. 72 func HasStack(err error) bool { 73 _, ok := err.(IStack) 74 return ok 75 } 76 77 // Equal reports whether current error `err` equals to error `target`. 78 // Please note that, in default comparison logic for `Error`, 79 // the errors are considered the same if both the `code` and `text` of them are the same. 80 func Equal(err, target error) bool { 81 if err == target { 82 return true 83 } 84 if e, ok := err.(IEqual); ok { 85 return e.Equal(target) 86 } 87 if e, ok := target.(IEqual); ok { 88 return e.Equal(err) 89 } 90 return false 91 } 92 93 // Is reports whether current error `err` has error `target` in its chaining errors. 94 // It is just for implements for stdlib errors.Is from Go version 1.17. 95 func Is(err, target error) bool { 96 if e, ok := err.(IIs); ok { 97 return e.Is(target) 98 } 99 return false 100 } 101 102 // HasError is alias of Is, which more easily understanding semantics. 103 func HasError(err, target error) bool { 104 return Is(err, target) 105 } 106 107 // callers returns the stack callers. 108 // Note that it here just retrieves the caller memory address array not the caller information. 109 func callers(skip ...int) stack { 110 var ( 111 pcs [maxStackDepth]uintptr 112 n = 3 113 ) 114 if len(skip) > 0 { 115 n += skip[0] 116 } 117 return pcs[:runtime.Callers(n, pcs[:])] 118 }