github.com/zly-app/zapp@v1.3.3/pkg/utils/recover.go (about) 1 /* 2 ------------------------------------------------- 3 Author : Zhang Fan 4 date: 2020/11/22 5 Description : 6 ------------------------------------------------- 7 */ 8 9 package utils 10 11 import ( 12 "errors" 13 "fmt" 14 "runtime" 15 "strings" 16 ) 17 18 type Caller struct { 19 PC uintptr 20 File string 21 Line int 22 } 23 24 type RecoverError interface { 25 error 26 Err() error 27 Callers() []*Caller 28 } 29 type recoverError struct { 30 err error 31 callers []*Caller 32 } 33 34 func (r recoverError) Error() string { 35 return r.err.Error() 36 } 37 func (r recoverError) Err() error { 38 return r.err 39 } 40 func (r recoverError) Callers() []*Caller { 41 return r.callers 42 } 43 func newRecoverError(err error) RecoverError { 44 var callers []*Caller 45 for i := 3; ; i++ { 46 pc, file, line, got := runtime.Caller(i) 47 if !got { 48 break 49 } 50 51 callers = append(callers, &Caller{ 52 PC: pc, 53 File: file, 54 Line: line, 55 }) 56 } 57 58 return recoverError{ 59 err: err, 60 callers: callers, 61 } 62 } 63 64 var Recover = new(recoverCli) 65 66 type recoverCli struct{} 67 68 func (*recoverCli) IsRecoverError(err error) bool { 69 _, ok := err.(RecoverError) 70 return ok 71 } 72 73 // 包装函数, 捕获panic 74 func (*recoverCli) WrapCall(fn func() error) (err error) { 75 // 包装执行, 拦截panic 76 defer func() { 77 e := recover() 78 if e == nil { 79 return 80 } 81 switch v := e.(type) { 82 case error: 83 err = v 84 case string: 85 err = errors.New(v) 86 default: 87 err = errors.New(fmt.Sprint(e)) 88 } 89 err = newRecoverError(err) 90 }() 91 92 err = fn() 93 return 94 } 95 96 // 获取 recover 错误 97 func (*recoverCli) GetRecoverError(err error) (RecoverError, bool) { 98 re, ok := err.(RecoverError) 99 return re, ok 100 } 101 102 // 获取 recover 错误的详情 103 func (*recoverCli) GetRecoverErrors(err error) []string { 104 re, ok := err.(RecoverError) 105 if !ok { 106 return []string{err.Error()} 107 } 108 109 var callers []string 110 callers = make([]string, len(re.Callers())+1) 111 callers[0] = err.Error() 112 for i, c := range re.Callers() { 113 callers[i+1] = fmt.Sprintf("%s:%d", c.File, c.Line) 114 } 115 return callers 116 } 117 118 // 获取 recover 错误的详情 119 func (*recoverCli) GetRecoverErrorDetail(err error) string { 120 re, ok := err.(RecoverError) 121 if !ok { 122 return err.Error() 123 } 124 125 var callers []string 126 callers = make([]string, len(re.Callers())+1) 127 callers[0] = err.Error() 128 for i, c := range re.Callers() { 129 callers[i+1] = fmt.Sprintf("%s:%d", c.File, c.Line) 130 } 131 return strings.Join(callers, "\n") 132 }