【新人系列】Golang 入门(九):defer 详解 - 下

✍ 个人博客:https://blog.youkuaiyun.com/Newin2020?type=blog
📝 专栏地址:https://blog.youkuaiyun.com/newin2020/category_12898955.html
📣 专栏定位:为 0 基础刚入门 Golang 的小伙伴提供详细的讲解,也欢迎大佬们一起交流~
📚 专栏简介:在这个专栏,我将带着大家从 0 开始入门 Golang 的学习。在这个 Golang 的新人系列专栏下,将会总结 Golang 入门基础的一些知识点,并由浅入深的学习这些知识点,方便大家快速入门学习~
❤️ 如果有收获的话,欢迎点赞 👍 收藏 📁 关注,您的支持就是我创作的最大动力 💪

1. 函数嵌套

我们再来看一个形如 defer(A(B©) 这样的例子,看看 defer 执行时参数 a 到底等于多少。

func B(a int) int {
   
   
    a++
    return a
}
func A(a int) {
   
   
    a++
    fmt.Println(a)
}
func main() {
   
   
    a := 1
    defer A(B(a))
    a++
    fmt.Println(a)
}

这个例子中,main 函数注册的 defer 函数是 A,所以 defer 链表中 _defer.fn 存储的是 A 的 funcval 指针。但是在 deferproc 执行时,需要保存 A 的参数到 _defer 结构体的后面,因此需要在这时候就拿到 defer 函数注册时 A 传入的参数,即需要此刻计算出 B(1) 的返回值作为参数传入。

在这里插入图片描述

所以 A 最终会得到 B(1) = 2 的参数进行传入,又因为该参数不存在捕获的条件即不会形成闭包,也就等于传入的这个参数固定下来了,后面再去修改参数 a 也不会影响到 defer 函数最终的结果。因此,最终 defer A(B(a)) 将会输出 3。

2. defer 嵌套

最后再来看一个 defer 嵌套的例子,这次抛开所有细节只看 defer 链表随着 A 的执行会怎样变化。

func A() {
   
   
    //......
    defer A1()
    //......
    defer A2()
    //......
}
func A2() {
   
   
    //......
    defer B1()
    defer B2()
    //......
}
func A1() {
   
   
    //......
}
//所有defer函数都正常执行......

首先函数 A 注册了两个 defer,这里途中我们用 A1 和 A2 函数名进行标记。

在这里插入图片描述

在函数 A 返回前执行 deferreturn 时,会判断 defer 链表头上的 defer 是不是 A 注册的。而这个方法就是判断 defer 结构体记录的 sp 是否等于 A 的栈指针,即判断 A2.sp == SP of A 是否成立。

如果是 A 注册的,就会保存函数的相关信息,就会把它从 defer 链表中移除并执行函数 A2,此时又会注册两个 defer,并记为 B1 和 B2。

在这里插入图片描述

在 A2 返回前同样会去执行 defer 链表,同样判断是否是自己注册的 defer 函数,即判断 B2.sp == SP of A2 是否成立。然

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值