什么是闭包(closure),用一句话来描述就是,闭包是一个函数和与他绑定的外部环境的集合。闭包在实现上是一个结构体,他存储了一个函数(通常是其入口地址)和一个关联的环境(相当于一个符号查找表)。环境中包含该函数的内部绑定符号,及其在外部定义但在函数中引用的自由变量。函数和闭包的不同在于,当捕获闭包的时候,他的自由变量会在捕捉时被确定,这样即使脱离了捕捉时的上下文,他也能照样运行。例如下面的例子:
func create() func()int{
c:=2
return func()int{
return c
}
}
func main(){
f1:=create()
f2:=create()
fmt.Println(f1())
fmt.Println(f2())
}
函数create() func()int
就是一个闭包,它有自由变量c,当create()函数执行结束,f1和f2依然能够正常调用这个闭包函数,获取捕获变量c的值。因为闭包包含捕获变量,所以在执行阶段才创建对应的闭包对象,假设create函数的指令入口为addr1,在堆上分配一个funcval的结构体,fn指向闭包函数入口,同时其捕获列表中捕获一个变量c,然后这个结构体的地址add2被赋值给f1。再次调用create函数,在分配一个funcval结构体,fn指向闭包函数入口addr1,在捕获对应的捕获变量,还是只有一个c,最后将这funcval的起始地址addr2赋值给f2。
func create() []func() int {
function := make([](func() int), 2, 2)
for i := 0;i < 2;i++ {
function[i] = func() int {
return i
}
i++
}
return function
}
func main() {
funcs := create()
fmt.Println(funcs[0]()) \\ 2
fmt.Println(funcs[1]()) \\ 2
}
捕获变量会发生改变时,捕获列表中保存的是捕获变量的地址,对捕获变量的修改会保持一致。因此,funcs[0]()
和funcs[1]()
两个函数获得的i
都是2。
本文来自:简书
感谢作者:小刀田田
查看原文:golang中的闭包
相关阅读 >>
更多相关阅读请进入《Go》频道 >>

Go语言101
一个与时俱进的Go编程知识库。