这是我的代码(运行):
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 }
输出:
0 1 2 3 4 4 3 2 1 0 4 4 4 4 4
问题:第2部分和第3部分有什么区别?为什么第2部分输出“ 44444”而不是“ 43210”?
“第2部分”闭包捕获变量“ i”。当闭包(稍后)中的代码执行时,变量“ i”具有在range语句的最后一次迭代中具有的值,即。‘4’。因此
4 4 4 4 4
输出的一部分。
“第3部分”在其闭包中未捕获任何外部变量。如规格所述:
每次执行“ defer”语句时,将照常评估调用的函数值和参数并重新保存,但不会调用实际函数。
因此,每个延迟的函数调用都具有不同的’n’参数值。它是执行defer语句时的’i’变量的值。因此
4 3 2 1 0
部分输出,因为:
…延迟调用将在周围函数返回之前立即按LIFO顺序执行…
需要注意的关键点是,在 执行 defer语句时,不会 执行 “ defer f()”中的“ f()”
但
当执行defer语句时,将 评估 “ defer f(e)”中的表达式“ e” 。