这是我的代码(运行):
package main
import "fmt"
func main() {
var whatever [5]struct{}
for i := range whatever {
fmt.Println(i)
} // part 1
for i := range whatever {
defer func() { fmt.Println(i) }()
} // part 2
for i := range whatever {
defer func(n int) { fmt.Println(n) }(i)
} // part 3
}
Run Code Online (Sandbox Code Playgroud)
输出:
0
1
2
3
4
4
3
2
1
0
4
4
4
4
4
问题:第2部分和第3部分有什么区别?为什么第2部分输出"44444"而不是"43210"?
zzz*_*zzz 38
'part 2'闭包捕获变量'i'.当闭包(后面)中的代码执行时,变量'i'具有它在range语句的最后一次迭代中具有的值,即.'4'.因此
4 4 4 4 4
Run Code Online (Sandbox Code Playgroud)
部分输出.
"第3部分"不会捕获其闭包中的任何外部变量.正如规格所说:
每次执行"defer"语句时,将像往常一样评估调用的函数值和参数,并重新保存但不调用实际函数.
因此,每个延迟函数调用都具有不同的'n'参数值.它是执行延迟语句时'i'变量的值.因此
4 3 2 1 0
Run Code Online (Sandbox Code Playgroud)
部分输出因为:
...在周围函数返回之前,延迟调用以LIFO顺序执行...
要注意的关键点是当defer语句执行时,'defer f()'中的'f()'不会被执行
但
当defer语句执行时,将评估 'defer f(e)'中的表达式'e' .
| 归档时间: |
|
| 查看次数: |
9814 次 |
| 最近记录: |