Golang闭包和匿名函数
1. 匿名函数
匿名函数就是没有函数名的函数,如下所示。
func test() int { max := func(a, b int) int { if a > b { return a } else { return b } }(3, 4) return max } func main() { primeCnt := make(chan int, 1) N := 10 go func(N int) { cnt := 0 for i := 2; i < N; i++ { var j int for j = 2; j <= int(math.Sqrt(float64(i))); j++ { if i%j == 0 { break } } if j > int(math.Sqrt(float64(i))) { cnt++ fmt.Println(i) } } primeCnt <- cnt }(N) fmt.Println("totalNum:", <-primeCnt) }
基本上匿名函数也没啥好说的 。。。
2. 闭包
闭包感觉就是返回值为匿名函数的函数。。。来看个例子吧 (◉3◉)
package main import ( "fmt" ) func squares() func() int { var x int return func() int { x++ return x * x } } func main() { f := squares() fmt.Println(f()) fmt.Println(f()) fmt.Println(f()) }
运行结果如下所示,可以看到三次调用f(),获得的是不同的x。即便是x是squares的局部变量,但是变量x的生命周期被延长到了三次函数调用( f() )。这是为什么呢?让我们在看看另一种情况。
package main import ( "fmt" ) func squares() func() int { var x int return func() int { x++ return x * x } } func main() { f := squares() f1 := squares() fmt.Println(f()) fmt.Println(f()) fmt.Println(f()) fmt.Println(f1()) fmt.Println(f1()) fmt.Println(f1()) }
看到了吧。换个变量就又重新开始了。嘿嘿嘿。为什么会这样,一句话,内存逃逸。什么是内存逃逸,简单地说就是本来在栈上的变量又跑到堆里去了。当然这么讲过于简单了,改天再写一文谈谈内存逃逸给各位太君,嘿嘿嘿。那么怎么才能检测程序有没有发生内存逃逸呢。go build工具就欧克了。如下图所示。
从图中我们可以看到变量x被移动到了堆中,这也就解释了为什么x的生命周期可以被延长。
参考
https://juejin.im/post/5c850d035188257ec629e73e 关于闭包的分析
《Go程序设计语言》