一、何为函数 闭包
闭包是由函数及其相关引用环境组合而成的实体,即闭包=函数+引用环境,比如
func f(i int) func() int{
return func() int{
i++
return i
}
}
函数f返回了一个函数,而返回的这个函数就是一个闭包,因为其引用了它所在的环境(函数f)中的变量i。
注意:闭包的环境中引用的变量是不能够在栈上分配的。
二、当函数闭包遇上defer
defer调用会在当前函数执行结束前才被执行,defer中使用匿名函数依然是一个闭包。
package main
import “fmt”
func main() {
x, y := 1, 2
defer func(a int) {
fmt.Printf(“a:%d,y:%d\n”, a, y) // y 为闭包引用
}(x) // 复制 x 的值,后面x的修改不会影响其参数a
x += 100
y += 100
fmt.Println(x, y)
}
输出结果:
101 102
x:1,y:102
原因: main函数会在defer匿名函数打印之前打印101 102,这一点无需解释;defer匿名函数中a的打印值为1,是因为函数在定义的时候就拷贝了x变量给a,y的打印值为102是因为闭包引用了外部main函数自由变量l的原因。
总结 :从形式上看,匿名函数都是闭包。闭包的使用非常灵活,不当的使用容易产生难以发现的 bug,当出现意外情况时, 首先检查函数的参数,声明可以接收参数的匿名函数 ,这些类型的闭包问题也就引刃而解了。