1)说明
go的异常捕获需要延迟函数defer + recover实现,在函数返回前,就可以捕获到, 这样其实比java的try catch更加优雅一点;
比如: web服务器程序崩溃前,需要做一些清理,那么就可以这样搞定;
还可以在捕获时,打印一些信息,继续panic,让错误往上抛
2)案例
package main
import (
"fmt"
"runtime"
)
type panicContext struct {
function string
}
func ProtectRun(entry func()) {
defer func() {
err := recover()
switch err.(type) {
case runtime.Error:
fmt.Println("runtime error:", err)
default:
fmt.Println("error:", err)
}
}()
entry()
}
func g() {
defer func() {
err := recover()
switch err.(type) {
case runtime.Error:
fmt.Println("g() runtime error:", err)
default:
fmt.Println("g() error:", err)
}
}()
var b *int
/*
注意: 这行改为*b = 1/0 这样, 被除数是0,直接编译报错
$ go build main.go
# command-line-arguments
.\main.go:38:8: division by zero
*/
*b = 1
}
func main() {
fmt.Println("运行前")
ProtectRun(func() {
fmt.Println("手动宕机前")
panic(&panicContext{"手动触发panic"})
fmt.Println("手动宕机后")
})
ProtectRun(func() {
fmt.Println("赋值宕机前")
var a *int
*a = 1
fmt.Println("赋值宕机后")
})
g()
fmt.Println("运行后")
}
/*
$ ./main.exe
运行前
手动宕机前
error: &{手动触发panic}
赋值宕机前
runtime error: runtime error: invalid memory address or nil pointer dereference
g() runtime error: runtime error: invalid memory address or nil pointer dereference
运行后
*/