Go 闭包

在 Go 中可以在一个函数里创建另一个函数。如下:

1
2
3
4
5
6
7
func main() {
add := func(x, y int) int {
return x + y
}
fmt.Println(add(1,1))
}

add 是一个属性为 func(int, int) int (两个 int 类型参数,返回值类型为 int 的函数)的局部变量。这样的局部函数还可以访问其他局部变量。

1
2
3
4
5
6
7
8
9
10
func main() {
x := 0
increment := func() int {
x++
return x
}
fmt.Println(increment())
fmt.Println(increment())
}

increment 函数为在 main 函数作用域中定义的变量 x 加1。 变量 x 可以被 increment 函数访问和修改。所以以上程序第一行将会输出:1,第二行将会输出:2。

这样的函数以及它引用的非本地变量称为闭包。 在本示例中,increment 函数和变量 x 形成闭包。

使用闭包的一种方法是编写一个函数,该函数返回另一个函数 - 当被调用时 - 可以生成一个数字序列。 例如,我们可以生成所有的偶数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func makeEvenGenerator() func() uint {
i := uint(0)
return func() (ret uint) {
ret = i
i += 2
return
}
}
func main() {
nextEven := makeEvenGenerator()
fmt.Println(nextEven()) // 0
fmt.Println(nextEven()) // 2
fmt.Println(nextEven()) // 4
}

makeEvenGenerator 返回一个生成偶数的函数。 每次调用它时,它会将2添加到本地i变量中 - 与正常的局部变量不同,它会在调用之间保持不变。

原文

Closure