看下面两段代码:
代码片段1:
package main
import (
"fmt"
)
func main() {
a := []int{1, 2, 3}
for _, value := range a {
fmt.Println(value)
defer p(value)
}
}
func p(value int) {
fmt.Println(value)
}
执行结果
1
2
3
3
2
1
代码片段2:
package main
import (
"fmt"
)
func main() {
a := []int{1, 2, 3}
for _, value := range a {
fmt.Println(value)
defer func() {
fmt.Println(value)
}()
}
}
执行结果
1
2
3
3
3
3
-
在Go的for…range循环中,Go始终使用值拷贝的方式代替被遍历的元素本身,简单来说,就是for…range中那个value,是一个值拷贝,而不是元素本身。也是说value是个局部变量,只是把元素赋值给该变量而已。
-
闭包里的非传递参数外部变量值是传引用的(非常重要),也就是闭包是地址引用。在闭包函数里那个value就是外部非闭包函数自己的参数,所以是相当于引用了外部的变量
-
有了以上两点的理解,再来理解代码2的结果就容易多了。闭包是通过地址引用来引用环境中的变量value,因此每次只是把value的地址拷贝了一份儿,就这样拷贝了三次。而执行到最后时value值为3,所以打印了3次value地址指向的值,所以是3,3,3。