Go 语言闭包(Closure)详解

闭包是 Go 中非常重要的概念,允许函数访问和操作其外部作用域的变量。理解闭包对于实现回调、累加器、工厂函数等场景非常有用。


一、闭包的概念

闭包是一个函数,它可以捕获并使用定义在其外部作用域的变量,即使外部函数已经返回,这些变量依然存在于内存中。

简单理解:

txt 复制代码
闭包 = 函数 + 它捕获的外部变量

二、基本示例

go 复制代码
package main

import "fmt"

func main() {
    add := func(a, b int) int {
        return a + b
    }

    fmt.Println(add(3, 5)) // 8
}

这是最基本的函数,也可以看作闭包,但没有捕获外部变量。


三、闭包捕获外部变量

go 复制代码
package main

import "fmt"

func adder() func(int) int {
    sum := 0
    return func(x int) int {
        sum += x
        return sum
    }
}

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

说明:

  1. adder 返回一个函数
  2. 返回的函数可以访问 adder 内部的 sum
  3. 每次调用返回函数,sum 都会累加,闭包保存了 sum 的状态

四、闭包注意事项

  1. 捕获变量是引用
go 复制代码
func main() {
    funcs := []func(){}
    for i := 0; i < 3; i++ {
        funcs = append(funcs, func() {
            fmt.Println(i)
        })
    }
    for _, f := range funcs {
        f() // 输出 3 3 3,而不是 0 1 2
    }
}

原因:

  • 闭包捕获的是 i 的地址,循环结束后 i = 3,所以每个闭包都打印 3。

解决办法:

go 复制代码
for i := 0; i < 3; i++ {
    x := i
    funcs = append(funcs, func() {
        fmt.Println(x)
    })
}

输出:

复制代码
0
1
2

  1. 闭包可以作为回调函数
go 复制代码
func callback(f func(int) int) {
    fmt.Println(f(10))
}

func main() {
    y := 5
    callback(func(x int) int {
        return x + y
    }) // 输出 15
}

闭包可以捕获外部变量 y


  1. 闭包的应用场景
  • 累加器(上例)
  • 工厂函数(生成自定义函数)
  • 回调函数
  • 延迟执行或装饰器模式

五、闭包总结

  1. 闭包 = 函数 + 捕获的外部变量
  2. 捕获的变量在闭包内是引用,修改会影响外部变量
  3. 循环中使用闭包需注意变量捕获问题
  4. Go 中闭包常用于累加器、回调和函数工厂
  5. 理解闭包是深入掌握 Go 函数式编程风格的关键
相关推荐
右耳朵猫AI1 小时前
Golang技术周刊 2026年第20周
开发语言·后端·golang
不吃土豆的马铃薯1 小时前
高性能服务器程序框架详解(包括Reactor,有限状态机等)
linux·服务器·开发语言·网络·c++
会编程的土豆1 小时前
Redis 常用操作笔记(Go 开发实战)
redis·笔记·golang
郝学胜-神的一滴1 小时前
Qt 高级开发 020:水平布局手写代码实战
开发语言·c++·qt·系统架构·软件构建·用户界面
小欣加油1 小时前
leetcode2126 摧毁小行星
数据结构·c++·算法·leetcode·职场和发展
BestOrNothing_20151 小时前
C++零基础到工程实战(5.2.6):函数与数组和数组引用
c++·数组·函数·数组引用·返回数组·参数数组
Mortalbreeze1 小时前
C++11 ---- 右值引用、值类型
开发语言·c++
少司府1 小时前
C++进阶:多态
c语言·开发语言·c++·多态·抽象类·虚函数·虚表指针
并不喜欢吃鱼1 小时前
从零开始 C++----- 十三【C++ 数据结构】哈希表从原理到手撕实现(开放定址 + 链地址全覆盖)
数据结构·c++·散列表