闭包概念

闭包(Closure)是匿名函数的一个特例。当一个匿名函数所访问的变量定义在函数体的外部时,就称这样的匿名函数为闭包。

闭包是由函数及其相关引用环境组合而成的实体(即:闭包=函数+引用环境)。

“官方”的解释是:所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。

维基百科讲,闭包(Closure),是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。

wiki 把高阶函数(Hiher-order Function)定义为:满足下列条件之一的函数:1)接收一个或多个函数作为参数;2)返回值是一个函数

Go的闭包

Go语言是支持闭包的。

每一个闭包都会绑定一个它自己的外围变量(Surrounding Variable)(函数和引用环境绑定)。

变量的值是函数执行时变量的值,即执行上下文变量的值。

注意:闭包中引用的变量不是函数参数或函数接收者,这些是及时计算并压栈的。

package main

import "fmt"

// 返回2个函数类型的返回值
func test01(base int) (func(int) int, func(int) int) {
    // 定义2个函数,并返回
    // 相加
    add := func(i int) int {
        base += i
        return base
    }
    // 相减
    sub := func(i int) int {
        base -= i
        return base
    }
    // 返回
    return add, sub
}

func main() {
    f1, f2 := test01(10)
    // base一直是没有消
    fmt.Println(f1(1), f2(2))
    // 此时base是9
    fmt.Println(f1(3), f2(4))
}
////
11 9
12 8

在汇编层 ,test 实际返回的是 FuncVal 对象,其中包含了匿名函数地址、闭包对象指针。当调匿名函数时,只需以某个寄存器传递该对象即可。

FuncVal { func_address, closure_var_pointer ... }

 

参考:

1. topgoer之闭包递归

2. 函数是一等公民(头等函数)