Go语言代码解析:是否会打印“defer”?
在Go语言的编程实践中,defer
语句是一个不可或缺的特性,它允许开发者延迟某个函数或方法的执行,直到包含该defer
语句的函数即将返回时才执行。这种特性在资源清理、互斥锁解锁、文件关闭等场景中扮演着重要角色。接下来,我们一同解析下面这段代码,探究其是否会打印出“defer”。
package main
import "fmt"
func main() {
var a int
defer func() {
if err := recover(); err != nil {
fmt.Println("recover")
}
}()
defer func() {
a = 1
fmt.Println("defer")
}()
fmt.Println(a)
panic("panic")
}
代码深度解析
(点击以下区域查看详细解析,不点击则隐藏)
点击查看详细解析
-
变量初始化:
- 声明了一个整型变量
a
,并将其初始化为零值(即0)。
- 声明了一个整型变量
-
第一个
defer
语句:- 注册了一个匿名函数,该函数包含一个恢复点(recover point),用于捕获可能发生的panic。如果panic发生并被recover捕获,它将输出“recover”。
-
第二个
defer
语句:- 注册了另一个匿名函数,该函数会修改变量
a
的值,并输出“defer”。
- 注册了另一个匿名函数,该函数会修改变量
-
打印变量
a
的初始值:- 由于变量
a
尚未被修改,因此会输出0。
- 由于变量
-
触发panic:
panic("panic")
这行代码会立即中断当前函数的执行,并开始逆序执行已经注册的defer
语句。
defer
的执行顺序与输出结果
- 当panic发生时,Go会逆序执行所有已注册的
defer
语句。 - 第一个被执行的
defer
是修改a
的值并输出“defer”的那个。因此,会先输出“defer”。 - 随后,检查是否有panic被recover捕获的
defer
被执行,捕获到panic并输出“recover”。
值得注意的是,虽然“defer”的输出操作发生在panic触发之后,但在程序真正崩溃(即完全退出)之前。一旦recover执行完毕,程序实际上已经从panic中恢复,但main函数已经结束,程序会正常退出。
总结
这段代码会打印出“defer”。在panic触发后,Go逆序执行了所有defer
语句。由于修改a
并打印“defer”的defer
语句在捕获panic的defer
语句之前注册,因此它会先被执行,从而打印出“defer”。随后,recover捕获到panic并打印“recover”,但程序最终会因main函数结束而退出。
希望这个解析能够帮助你更加深入地理解Go中defer
和panic/recover
的工作机制。