一道题目
func f(n int) (r int) {
defer func() {
r += n
recover()
}()
var fn func()
defer fn()
fn= func() {
r += 2
}
return n + 1
}
func main() {
fmt.Println(f(3))
}
输出结果为7,有几个知识点
-
return语句的执行是非原子的,分为两步,第一步是为返回值赋值,第二步是返回到函数调用处
-
当函数的返回值是无名返回值时,在第一步会创建一个临时零值变量,对这个临时变量进行赋值
func f() int { var i int defer func() { i++ fmt.Println("deferred func:", i) // 打印结果为 deferred func: 1 }() return i func main() { fmt.Println("return:", f()) // 打印结果为 return: 0 }
这里return语句实际上执行了
var temp int temp = i // execute deferred function return temp
-
当函数的返回值为有名值时,这个临时变量不会被创建,而是使用有名返回值进行返回,意味着在defer函数中有可能在return的第一步即返回值赋值后继续修改返回值(因为返回值变量名称已知,即可被访问)
-
-
defer的函数在return的第一步后执行,即上述注释处
-
defer的函数必须在注册前定义,否则不会生效,对只声明而不定义的函数进行defer会引发nil pointer deference panic