github.com/sohaha/zlsgo@v1.7.13-0.20240501141223-10dd1a906f76/zerror/format.go (about) 1 package zerror 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "runtime" 8 "strings" 9 10 "github.com/sohaha/zlsgo/zutil" 11 ) 12 13 // Error returns msg 14 func (e *Error) Error() string { 15 if e == nil || (e.err == nil && e.errText == nil) { 16 return "<nil>" 17 } 18 19 if e.errText != nil { 20 return *e.errText 21 } 22 23 if e.inner && e.wrapErr != nil { 24 return e.wrapErr.Error() 25 } 26 27 return e.err.Error() 28 } 29 30 // Unwrap returns err inside 31 func (e *Error) Unwrap() error { 32 if e == nil { 33 return nil 34 } 35 return e.wrapErr 36 } 37 38 // Format formats the frame according to the fmt.Formatter interface 39 func (e *Error) Format(s fmt.State, verb rune) { 40 switch verb { 41 case 'v': 42 switch { 43 case s.Flag('-'): 44 _, _ = io.WriteString(s, e.Error()) 45 default: 46 tip := strings.Join(UnwrapErrors(e), ": ") 47 _, _ = io.WriteString(s, tip+"\n"+e.Stack()) 48 } 49 case 's': 50 _, _ = io.WriteString(s, strings.Join(UnwrapErrors(e), ": ")) 51 } 52 } 53 54 // Stack returns the stack callers as string 55 func (e *Error) Stack() string { 56 if e == nil { 57 return "" 58 } 59 loop, i, buffer := error(e), 1, zutil.GetBuff() 60 defer zutil.PutBuff(buffer) 61 for { 62 if loop == nil { 63 break 64 } 65 e, ok := loop.(*Error) 66 if ok { 67 if e.stack != nil { 68 if e.err != nil { 69 buffer.WriteString(fmt.Sprintf("%d. %-v\n", i, e.err)) 70 } else { 71 buffer.WriteString(fmt.Sprintf("%d. %-v\n", i, e)) 72 } 73 i++ 74 formatSubStack(e.stack, buffer) 75 } 76 if e.wrapErr != nil { 77 if en, ok := e.wrapErr.(*Error); ok { 78 loop = en 79 } else { 80 loop = e.wrapErr 81 if loop == nil { 82 break 83 } 84 buffer.WriteString(fmt.Sprintf("%d. %s\n", i, loop.Error())) 85 break 86 } 87 } else { 88 break 89 } 90 } 91 } 92 return buffer.String() 93 } 94 95 // formatSubStack formats the stack for error 96 func formatSubStack(st zutil.Stack, buffer *bytes.Buffer) { 97 if st == nil { 98 return 99 } 100 index := 1 101 space := " " 102 st.Format(func(fn *runtime.Func, file string, line int) bool { 103 if strings.Contains(file, "<") { 104 return true 105 } 106 if goROOT != "" && strings.HasPrefix(file, goROOT) { 107 return true 108 } 109 if index > 9 { 110 space = " " 111 } 112 113 buffer.WriteString(fmt.Sprintf( 114 " %d).%s%s\n \t%s:%d\n", 115 index, space, fn.Name(), file, line, 116 )) 117 index++ 118 return true 119 }) 120 }