53.蛤蟆笔记go语言——defer,panic,recover使用场景
defer
defer 调用的函数将被暂时保存到调用列表中. 保存的调用列表在当前环境返回的时候被执行. Defer 一般可以用于简化代码, 执行各种清理操作.
Defer语句的行为简单且可预测. 有三个基本原则:
1. 当defer调用函数的时候, 函数用到的每个参数和变量的值也会被计算
2. Defer调用的函数将在当前函数返回的时候, 以后进先出的顺序执行.
3. Defer调用的函数可以在返回语句执行后读取或修改命名的返回值. 利用该特性, 我们可以方便修改函数的错误返回值.
Panic
Panic 是一个内置的函数: 停止当前控制流, 然后开始panicking. 当F函数调用panic, F函数将停止执行后续的普通语句, 但是之前的defered函数调用仍然被正常执行, 然后再返回到F的调用者. 对于F函数的调用者, F 的行为和直接调用panic函数类似. 以上的处理流程会一直沿着调用栈回朔, 直到当前的goroutine返回引起程序崩溃! Panics可以通过直接调用panic方式触发, 也可以由某些运行时错误触发, 例如: 数组的越界访问.
recover
Recover 也是一个内置函数: 用于从 panicking 恢复. Recover 和 defer 配合使用会非常有用. 对于一个普通的执行流程, 调用recover将返回nil, 也没有任何效果. 但如果当前goroutine处于 panicking状态, recover调用会捕获触发panic时的参数, 并且恢复到正常的执行流程.
示例代码如下:
packagemain
import"fmt"
funcmain(){
f()
fmt.Println("Returnednormallyfromf.")
}
funcf(){
deferfunc(){
ifr:=recover();r!=nil{
fmt.Println("Recoveredinf",r)
}
}()
fmt.Println("Callingg.")
g(0)
fmt.Println("Returnednormallyfromg.")
}
funcg(iint){
ifi>3{
fmt.Println("Panicking!")
panic(fmt.Sprintf("%v",i))
}
deferfmt.Println("Defering",i)
fmt.Println("Printinging",i)
g(i+1)
}
执行如下:
Calling g.
Printing in g 0
Printing in g 1
Printing in g 2
Printing in g 3
Panicking!
Defer in g 3
Defer in g 2
Defer in g 1
Defer in g 0
Recovered in f 4
Returnednormally from f.
defer 语句(不管是否包含panic 和 recover)提供了一种不同寻常且十分强大的控制流机制. 它可以用于模拟一些其他语言中的某些特殊的语法结构.
有疑问加站长微信联系(非本文作者)