go defer需要弄清楚的三个点

本文探讨了Go语言中defer的三大核心要点:在函数结束前遇到panic时的行为、多个defer调用的执行顺序以及defer参数的确切确定时机。通过实例演示了defer在异常处理、调用顺序及参数捕获上的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本篇主要记录defer的三个关键点。

我们知道defer调用会在函数结束时被执行,但除此之外,我们还应该弄清楚几个问题:

函数结束前遇到panic,defer调用还会执行吗?

多个defer的调用顺序是怎么样的?

defer的参数是调用时确定的还是执行时?

下面结合例子,逐个说明一下。

遇到panic时,panic之前的defer会执行

其实这点不算是defer的知识点,算是panic的流程。程序发生panic时,会一层一层的返回,查找有没有recover,返回的过程中遇到的所有defer都会执行,因为recover一定是在defer调用的。可以写段简单的程序试验下。

package main

import "fmt"

func print(a int)  {
	fmt.Println(a)
}

func main()  {
	a, b := 2, 0
	defer print(a)
	fmt.Println(a / b)
	defer print(b)
}

运行结果如下:

a/b时,由于b是0,所以出现了panic,但是panic上面defer调用的print(a)还是执行了,而panic后面的print(b)则没有执行。

多个defer,按照后进先出的顺序执行

defer在调用时,会将执行的内容先存入栈中,到函数执行结束,再将栈中的调用依次取出执行。

我们试验一下,先defer print(a),再defer print(b)。

package main

import "fmt"

func print(a int)  {
	fmt.Println(a)
}

func main()  {
	a, b := 2, 0
	defer print(a)
	defer print(b)
	fmt.Println("main is running")
}

运行结果如下:

可以看到,print(b)在print(a)之前被执行了。

defer调用的参数,是调用时确定的

defer调用如果传入了一个变量,而这个变量在函数运行过程中被改变了,等到函数结束执行defer调用的时候,defer调用的参数,还是调用的时候那个值,这是因为变量的值和defer调用一起,在调用的时候,已经存入了栈中。

还是简单验证一下。

package main

import "fmt"

func print(a int)  {
	fmt.Println(a)
}

func main()  {
	a := 2
	defer print(a)
	a = 3
	fmt.Println("main is running, a=", a)
}

运行结果如下:

可以看到a虽然被改变了,但是最后执行的print(a),打印的还是defer调用时候的值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值