零基础 go - 35(函数 - 闭包)

5 阅读2分钟

闭包就是一个函数和与其相关的引用环境组合而成的整体。换句话说,闭包允许函数访问并操作函数外部的变量,即使外部函数已经返回。

一、闭包的要素包括:

  1. 函数:闭包必须包含一个函数,可以是匿名函数或具名函数。
  2. 引用环境:闭包必须引用至少一个外部变量,这些变量在函数定义时存在,并且在函数执行时仍然可访问。

二、闭包的作用:

  1. 数据封装:闭包可以将函数内部的变量封装起来,防止外部直接访问和修改,从而实现数据的私有化。
  2. 维持状态:闭包可以维持函数执行时的状态,即使外部函数已经返回,闭包仍然可以访问和修改这些状态。

三、示例

  • Calc 是一个函数,返回的类型是 func(y int) int,这个返回的函数就是一个闭包。
  • 闭包内部访问了外部函数 Calc 的变量 count,并且每次调用闭包时都可以修改这个变量。
  • 当我们反复调用 c 函数时,count 只初始化一次,并且在每次调用 c 时都会累加 y 的值,体现了闭包维持状态的特性。
package main

import "fmt"

// 闭包
func Cal(x int) func(y int) int {
    count := x // 定义一个外部变量 count
    
    return func(y int) int {
        count += y // 内层函数访问并修改外部变量 count
        return count
    }
}

func main() {
    c := Cal(10) // 调用 Cal 函数,返回一个闭包函数
    fmt.Println(c(1)) // 输出 11
    fmt.Println(c(1)) // 输出 12
    fmt.Println(c(1)) // 输出 13
}

四、使用普通函数实现上面 Cal 函数的效果,需要通过指针参数传递和修改外部变量,这样会使得函数调用变得复杂和不直观。而使用闭包则可以直接访问和修改外部变量,使得代码更加简洁和易读。

package main

import "fmt"

func Cal1(c1 *int, y int) *int {
    *c1 += y // 通过指针参数传递和修改外部变量
    return c1
}

func main() {
    c1 := 10 // 需要额外定义一个外部变量 c1
    fmt.Println(Cal1(&c1, 1)) // 输出 11
    fmt.Println(Cal1(&c1, 1)) // 输出 12
    fmt.Println(Cal1(&c1, 1)) // 输出 13
}