Go闭包

闭包

Go 的函数可以是一个闭包,我对于闭包的理解就是一个函数里面定义一些变量,然后返回一个函数
在调用这个函数的时候,里面那个返回的函数就会被”赋值”给调用处接收的变量,这个变量就可以当一个函数使用,并且可以使用外层函数的变量
有点绕,使用闭包的好处就是在外层函数定义的变量可以一直被使用,它在调用这个函数之后不会被释放,它保存的值可以在下一次调用时使用

理解

比如如下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
func adder() func(int) int {
sum := 0
return func(x int) int {
sum += x
return sum
}
}

func main() {
pos, neg := adder(), adder()
fmt.Println("pos")
for i := 0; i < 10; i++ {
fmt.Println(pos(i))
}
fmt.Println("neg")
for i := 0; i < 10; i++ {
fmt.Println(neg(i*2))
}
}

看了代码就很清晰了,调用了两次 adder(),函数,然后将两个函数的返回值(也就是adder()里面的闭包函数)赋给了 pos 和 neg 两个变量
此时, pos 和 neg 这两个变量实质上是两个函数
如下是我对此时的 pos 和 neg 状态的理解

1
2
3
4
pos func(x int) int{
sum += x
return sum
}
1
2
3
4
neg func(x int) int{
sum += x
return sum
}

里面 sum 变量看上去是没有定义,其实已经定义了,在调用 adder() 函数的时候就已经定义了
sum 这个变量就跟着调用它的变量”绑定”在了一起,只有这个变量(实质上是个函数)被销毁了,它才会跟着被销毁
所以 pos 和 neg 它们有着各自的 sum 虽然名字一样,但互不干扰,永远是它们自己的 sum

理解了闭包是怎么回事了,程序运行的结果也就明了了
pos 依次传入 0~9 共10个数,每传一次输出一次 sum
于是结果就是

1
2
3
4
5
6
7
8
9
10
11
12
初始 sum := 0
pos //sum+传入的值
0 //0+0
1 //0+1
3 //1+2
6 //3+3
10 //6+4
15 //10+5
21 //15+6
28 //21+7
36 //28+8
45 //36+9

同理 neg 就是依次传入 0~18 间隔为2的共10个数,每传一次输出一次 sum

1
2
3
4
5
6
7
8
9
10
11
12
初始 sum := 0
neg //sum+传入的值
0 //0+0
2 //0+2
6 //2+4
12 //6+6
20 //12+8
30 //20+10
42 //30+12
56 //42+14
72 //56+16
90 //72+18

斐波纳契闭包函数

这是在 Tour of Go 里面学习闭包时的练习,拿来理解闭包更方便一点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 返回一个“返回int的函数”
func fibonacci() func() int {
i, j := 0, 1
return func() int{
temp := i
i, j = j, (i+j)
return temp
}
}

func main() {
f := fibonacci()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
}

有了前面的理解,就不难看出 i 和 j 两个变量和 f 是”绑定”在了一起的
i 和 j 的初始值为 0 和 1
每调用一次 f 就会把此时的 i 的值赋给 temp ,然后将此时的 j 赋给 i, 此时的 i+j 赋给 j
最后返回 temp
每一次 i 和 j 的值都是上一次调用后的结果,不会回到最开始的初值


这算是弄懂了闭包吧 (・ω´・ )
以前学 Python 的时候碰到过闭包,但没理解透彻就放弃了
现在算是理解了吧 Ciallo~(∠・ω< )⌒★