答案:7
解析:
首先,defer 是和返回值被命名的函数一起使用的,而且 defer 语句定义时对外部变量引用的方式是闭包引用(细节可参考文章:关于defer坑坑洼洼的使用细节你mark了吗,建议先看完文章再往下看,否则有的同学可能会有点接不上)
为什么第二个 defer 不起作用呢?其实第二个 defer 的延迟函数啥都没干,甚至程序执行到 f() 时还抛出 panic 了。我们都知道 程序在执行到 defer 定义时并不会马上执行,而是对捕捉到的 defer 结果进行链表构建,把关联的函数入栈缓存,在程序 return 前再进行出栈执行。那么问题就很明显了,我们看在程序执行到 defer f() 时,此时的 f 是啥?此时的 f 的值为 nil,所以最后出栈执行一个nil 函数,就相当于:
var f func()
f() // panic: runtime error: invalid memory address or nil pointer dereference
因此这也是为什么第一个 defer 为什么要有 recover() 方法。后面的 f = func() { r += 2 } 是赋值操作,对返回值 r 没影响