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