A. 什么是闭包?

闭包 (Closure) 是指一个函数和与其相关的引用环境组合而成的整体 ****。更具体地说, 闭包是一个函数, 它引用了自身函数外部的变量。这个引用的变量就构成了函数的引用环境 ****。

B. 闭包的例子

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
func getSum() func(int) int {
    var sum int = 0
    return func(num int) int {
        sum = sum + num
        return sum
    }
}

func main() {
    f := getSum()
    fmt.Println(f(1)) //1
    fmt.Println(f(2)) //3 
    fmt.Println(f(3)) //6
    fmt.Println(f(4)) //10
}

在这个例子中:

  1. getSum 函数返回一个匿名函数。
  2. 这个匿名函数引用了 getSum 函数中的 sum 变量。
  3. 因此, 返回的匿名函数和 sum 变量组合在一起, 构成了一个闭包 ****。
  4. 每次调用这个匿名函数时, 它会记住并更新 sum 变量的值。

C. 闭包的特点

  1. 引用了外部变量: 闭包引用并使用了函数外部的变量。
  2. 变量长期驻留内存: 闭包中引用的外部变量会一直保存在内存中, 直到闭包不再使用它们。这意味着闭包的使用需要谨慎, 避免滥用导致内存泄漏。
  3. 封装私有变量: 闭包可以用来封装一些私有变量, 避免被外部直接访问。

D. 不使用闭包的替代方案

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
func getSum01(sum int, num int) int {
    sum = sum + num
    return sum
}

func main() {
    fmt.Println(getSum01(0, 1)) //1
    fmt.Println(getSum01(1, 2)) //3
    fmt.Println(getSum01(3, 3)) //6 
    fmt.Println(getSum01(6, 4)) //10
}

这个例子中, getSum01 函数每次都需要传入之前的 sum 值和新的 num 值。这种方式没有使用闭包, 因此无法保留之前的状态。

闭包的主要优势在于可以保留上次引用的某个值, 从而实现状态的持久化。 在一些需要记录状态的场景下, 闭包可以提供一种优雅的解决方案。但同时也需要注意闭包可能导致的内存泄漏问题。