golang异常捕获后,可以记录堆栈信息到日志,方便以后分析,同时异常捕获后,主程序可以继续运行;
-
recover初级用法
示例代码如下:
package main import ( "fmt" "runtime/debug" "time" ) func PanicTrace() { if err := recover(); err != nil { fmt.Println("panic:", err, ", stack:", string(debug.Stack())) } } func main() { go func() { defer PanicTrace() // 加入异常捕获 var infoMap map[int]string infoMap[1] = "a" // 这里map未初始化直接调用导致协程异常 }() time.Sleep(2 * time.Second) fmt.Println("Exit.") // 主协程依然可以正常执行 }
执行结果如下:
panic: assignment to entry in nil map , stack: goroutine 5 [running]: runtime/debug.Stack(0xc04203de98, 0x4a4960, 0x4cfda0) C:/Go/src/runtime/debug/stack.go:24 +0xae main.PanicTrace() C:/antelop/gopath/src/test/main.go:11 +0x75 panic(0x4a4960, 0x4cfda0) C:/Go/src/runtime/panic.go:502 +0x237 main.main.func1() C:/antelop/gopath/src/test/main.go:20 +0x66 created by main.main C:/antelop/gopath/src/test/main.go:16 +0x3c Exit.
-
recover进阶用法
上面的方法需要在每个协程函数的最开始位置添加“defer PanicTrace()”的调用,当协程比较多时,比较容易忘记调用该方法,下面对recover进行进一步封装:
package main
import (
"fmt"
"runtime/debug"
"time"
)
// WithRecover将协程方法直接封装进来调用
func WithRecover(fn func()) {
defer func() {
if err := recover(); err != nil {
fmt.Println("panic:", err, ", stack:", string(debug.Stack()))
}
}()
fn()
}
func GoFunc() {
var infoMap map[int]string
infoMap[1] = "a" // 这里map未初始化直接调用导致协程异常
}
func main() {
// 协程方法调用进一步封装
go WithRecover(GoFunc)
time.Sleep(2 * time.Second)
fmt.Println("Exit.")
}