package main
import (
"fmt"
)
func main() {
var fs = [4]func(){}
for i := 0; i < 4; i++ {
defer fmt.Println("defer i = ", i)
defer func() { fmt.Println("defer_closure i=", i) }()
fs[i] = func() { fmt.Println("closure i=", i) }
}
for _, f := range fs {
f()
}
}
该段代码的输出为:
解释一下输出的原因:
由于defer就像一个栈一样,所以前面的defer输出语句以及函数调用都是用栈存储起来最后输出,所以最先输出的是:
for _, f := range fs {
f()
}
由于fs在之前的循环中都已经进行了赋值,所以会直接调用相应的函数,可是为什么答案不是输出0,1,2,3而是输出四个4呢?
原因很简单,是因为
fs[i] = func() { fmt.Println("closure i=", i) }
这个函数是个空名函数,由于并没有参数传进来,可是他要输出i,那么程序只有向外层查找i变量,然后记录下i的地址,需要用的时候再去输出,所以程序执行到最后的时候i的地址对应的值是4,所以就全部输出了4。所以第一个for循环里面的defer函数也是同样的道理。
但是第一个for的defer直接输出语句,是因为输出函数里面的i是作为参数,有数值的拷贝过程,所以因此会输出0,1,2,3。