github.com/searKing/golang/go@v1.2.117/error/builtin/recover.go (about) 1 // Copyright 2020 The searKing Author. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package builtin 6 7 import ( 8 "fmt" 9 "io" 10 "net" 11 "os" 12 "strings" 13 "time" 14 ) 15 16 // The Recover function allows a program to manage behavior of a 17 // panicking goroutine. 18 // affect as recoverHandler(recover()) 19 // brokenPipeMsg is called when panic for broken pipe 20 func Recover(writer io.Writer, recoverHandler func(err any) any, brokenPipeMsg func() string) any { 21 if err := recover(); err != nil { 22 // Check for a broken connection, as it is not really a 23 // condition that warrants a panic stack trace. 24 var brokenPipe = ErrorIsBrokenPipe(err) 25 if writer != nil { 26 goErr := fmt.Errorf("panic %v", err) 27 28 var msg string 29 if brokenPipeMsg != nil { 30 msg = brokenPipeMsg() 31 } 32 33 if brokenPipe { 34 _, _ = writer.Write([]byte(fmt.Sprintf("[Recovery] brokenPipe %+v\n%s", goErr, msg))) 35 } else { 36 _, _ = writer.Write([]byte(fmt.Sprintf("[Recovery] %s panic recovered:\n%+v", 37 timeFormat(time.Now()), goErr))) 38 } 39 } 40 if recoverHandler != nil { 41 return recoverHandler(err) 42 } 43 return err 44 } 45 return nil 46 } 47 func timeFormat(t time.Time) string { 48 var timeString = t.Format("2006/01/02 - 15:04:05") 49 return timeString 50 } 51 52 func ErrorIsBrokenPipe(err any) bool { 53 var brokenPipe bool 54 if ne, ok := err.(*net.OpError); ok { 55 if se, ok := ne.Err.(*os.SyscallError); ok { 56 if strings.Contains(strings.ToLower(se.Error()), "broken pipe") || strings.Contains(strings.ToLower(se.Error()), "connection reset by peer") { 57 brokenPipe = true 58 } 59 } 60 } 61 return brokenPipe 62 }