golang 中的陷阱. 这是一个有趣的例子,用到了 loop, defer 和闭包.
例子 1,输出全是 5, 例子 2 和例子 3 会输出 5 4 3 2 1 0.
// 1
package main
import "fmt"
func main() {
var whatever [6]struct{}
for i := range whatever {
defer func() {
fmt.Println(i)
}()
}
/*
为什么全是 5,为什么不是 0, 1, 2, 3, 4, 5 这样的输出结果呢?
其根本原因是闭包所导致的,有两点原因:
1. 在 for 循环结束后,局部变量 i 的值已经是 5 了,并且 defer 的闭包是直接引用变量的 i。
2. 结合defer 关键字的特性,可得知会在 main 方法主体结束后再执行。
结合上述,最终输出的结果是已经自增完毕的 5。
*/
}
//2
package main
import "fmt"
func main() {
var whatever [6]struct{}
for i := range whatever {
y := i
defer func() {
fmt.Println(y)
}()
}
}
//3
package main
import "fmt"
func main() {
var whatever [6]struct{}
for i := range whatever {
defer func(i int) {
fmt.Println(i)
}(i)
}
}
defer 执行顺序是先进后出的倒序执行.
例子 2 中用局部变量声明的方式把的值拷克了.因此输出结果和例子 1 不同.
例子 3 中,defer 执行的函数的参数是由声明时确定的.因此输出结果和例子 1 不同.
来源: https://eddycjy.com/posts/go/go-tips-defer/