golang学习笔记之panic recover

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.")
}

你可能感兴趣的:(golang学习笔记之panic recover)