go异常处理
func try(block func(), catch func(e interface{}), finally func()) {
defer func() {
e := recover() // 当block中panic时,recover将返回panic的参数
if e != nil { // 当block中没有panic时,recover将返回nil
catch(e)
}
if finally != nil {
finally()
}
}()
block() // 当block中panic时,recover将返回panic的参数
}
测试:
func foo() {
a := [...]int{1, 2, 3, 4, 5}
for i := 0; ; i++ {
fmt.Println(a[i]) // 这里会越界,导致panic
}
}
func main() {
try(func() {
foo()
}, func(e interface{}) {
fmt.Println("catch:", e)
}, func() {
fmt.Println("finally")
})
}
输出:
1
2
3
4
5
catch: runtime error: index out of range
finally
分析
按照go语言的说法,panic被认为是程序bug,也就是可以避免的错误,相当于java中unchecked exception
这种错误最好就是让程序及早crash,以便修复bug,而不是去catch错误。
而正常的程序错误是用error来表示,通过函数返回值来报告错误,这样的错误也叫做expected error,就是避免不了的,比如用户输入不合法,io错误等,这是程序作者控制不了的,这样的错误需要检查,相当于java中的checked exception
总结:
基本上panic的使用场景有
- 在main函数中catch panic,并记录一下异常以及stack trace等信息,然后调用panic(e),相当于rethrow异常,让程序崩溃。
- 对于server类的长期运行程序,有必要捕获由于请求的handler造成的panic,并记录日志,避免程序crash。