Golang小菜-defer

本文详细解析defer关键字的工作原理,涉及函数调用顺序、参数求值和非原子性return的影响,通过实例演示如何影响程序输出结果。

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

defer 关键字在我们日常开发中是出现频率极高的。

defer语句用于延迟调用指定的函数,比如释放资源,锁释放等。

如下,database操作完成后断开链接(随手写的代码)。

func process() {
    cli,err := db.connect("url")
    if err != nil{
        log.Fatal(err)
    }
    defer cli.disconnect()

    cli.insert(.....)
}

但是defer也是一道辣嗓子的菜,不好好掌握是会在面试时吃大亏的。

第一题

type number int

func main(){
	var v number = 0
	
	v.Print(1)
	
	defer v.Print(2).Print(3)

	v.Print(4)
}

func (n number) Print(a number) number{
	fmt.Println(a)
	
	return n
}

输出结果:1 2 4 3

解析:

1.先执行第6行,所以输出1 没有问题

2.defer 语句入栈前需要对参数求值, 这里的参数指的是 Print(3)的调用者 -> v.Print(2),  在求 v.Print(2)的返回值时会输出 2. 所以第二个值是 2. 然后2.Print(3) 入栈等待执行

3. 执行第10行 输出 4

4.执行 defer的语句 2.Print(3) 输出 3

简单版

func a() {
	i := 0
	defer fmt.Println(i)
	i++
	return
}

输出结果:0

第二题

func main(){
	fmt.Print(f())
}

func f() (res int) {
	defer func() {
		res++
	}()
	return 0
}

输出结果:1

解析:

1. golang的return操作是非原子性的,所以return 0 可以理解为 result = 0,return result

2. 在执行 return result(0)后,defer 对 result ++, 所以 result = 1,输出 1

我们可以把f() 理解成这样

func f() (res int) {
    res = 0
    func(){
        res ++
    }()
    return res
}

第三题

func main() {
	fmt.Print(f())
}

func f() (res int) {
	num := 1
	defer func() {
		num += 3
	}()
	return num
}

输出结果:1

解析:

该题与第二题其实原因一样。我们可以把 f() 理解成

func f() (res int) {
	num := 1

	res = num
	func() {
		num += 3
	}()

	return res
}

所以 t 的修改对 result 值本身没有任何影响,也就不影响最终的返回结果了

第四题

func main() {
	fmt.Print(f())
}

func f() (res int) {
	defer func(r int) {
		r = r + 5
	}(res)
	return 1
}

输出结果: 1, 可能这个是大家最不能理解的了

解析:

1. 我们先按照前两题解题方式重写函数来理解,像这样

func f() (res int) {
	res = 1

	func(num int){
		num += 5
	}(res)

	return res
}

2. 题目原代码第5行的 r 是 传入的 result 的副本。 也就是说,r 的修改不影响 result 的值。

 

总结

1. defer 是在 函数返回前 执行

2. return的操作是非原子性的

3. defer 语句会在入栈前求出 参数的具体值

 

到此结束。

有问题,或者建议请留言,谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值