所谓匿名函数就是没有名字的函数,我们在golang的代码中经常看到,常见的匿名函数一般如下形式
//不带参数,a()输出1 a := func() { fmt.Println(1) } //带参数a(1)输出1 b := func(arg int) { fmt.Println(arg) } //带返回值,c()的返回值为5 c := func() int { fmt.Println(4) return 5 }
我们先列出来这几种函数,为我们接下来看闭包打下一点基础
我们先不给闭包下定义,我们先看下现象
package main import "fmt" func A() func(int) int { sum := 0 return func(bb int) int { sum += bb fmt.Println("bb=", bb, "\tsum=", sum) return sum } } func main() { a := A() a(0) a(1) a(5) }
看下运行的结果
我们看到一个奇怪的现象,sum的值貌似被累加了,为什么呢?这里其实就是形成了一个闭包,当创建a函数的时候,A函数把sum组装给了这个返回函数,组装进去的是它的引用,所以引起了累加现象,另外我们从逃逸分析方面验证下
看到没有,装载进a函数的事sum的引用,并且逃逸到了堆上,所以在A函数执行完之后,并不会释放掉sum。 另外我们注意掉貌似bb也被逃逸了啊,为什么它没有被累加呢,仔细看我们的bb是返回的函数a的参数穿进去的,是值传递喔。 我们继续看如下的代码
package main import "fmt" func A() func(int) int { sum := 0 return func(bb int) int { sum += bb fmt.Println("bb=", bb, "\tsum=", sum) return sum } } func main() { a := A() c := A() a(0) a(5) c(10) c(20) }
哟,看起来不对啊,sum没有被四次累加啊,看下逃逸分析
还是发现不了啊,难道不对?其实仔细向下,我们调用了两次A函数,sum变量是在A函数中被创建的,所以a函数的sum的引用与c函数中的sum的引用必然不是一个啊,所以这也就是它们各自行程了自己的闭包。