全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-13 6 分钟 ✍️ juanwangdev

Go匿名函数与闭包

Go匿名函数无需命名,闭包可捕获并持有外部变量。

匿名函数

定义与调用

Go
// 定义并立即调用
func() {
    fmt.Println("匿名函数")
}()

// 带参数
func(a, b int) {
    fmt.Println(a + b)
}(1, 2)

// 带返回值
result := func(a, b int) int {
    return a + b
}(1, 2)

赋值给变量

Go
// 匿名函数赋给变量
add := func(a, b int) int {
    return a + b
}

// 作为普通函数调用
result := add(1, 2)

作为参数传递

Go
// 函数作为参数
func process(fn func(int) int, n int) int {
    return fn(n)
}

// 传递匿名函数
result := process(func(n int) int {
    return n * 2
}, 5)
fmt.Println(result)  // 10

闭包

基本概念

Go
// 闭包:函数 + 它引用的外部变量
func counter() func() int {
    count := 0  // 外部变量

    return func() int {
        count++  // 引用并修改外部变量
        return count
    }
}

c := counter()
fmt.Println(c())  // 1
fmt.Println(c())  // 2
fmt.Println(c())  // 3

闭包"记住"并持有外部变量,每次调用共享同一变量。

闭包持有变量

Go
func adder(base int) func(int) int {
    return func(n int) int {
        return base + n  // 持有base变量
    }
}

add5 := adder(5)
add10 := adder(10)

fmt.Println(add5(3))   // 8  (5 + 3)
fmt.Println(add10(3))  // 13 (10 + 3)
// add5和add10持有不同的base

闭包陷阱

循环变量捕获

Go
// 陷阱:所有闭包引用同一变量
for i := 0; i < 3; i++ {
    defer func() {
        fmt.Println(i)  // 可能打印 3, 3, 3
    }()
}

// 解决:传递参数
for i := 0; i < 3; i++ {
    defer func(n int) {
        fmt.Println(n)  // 打印 2, 1, 0
    }(i)
}

goroutine中的闭包

Go
// 陷阱:共享变量
for i := 0; i < 3; i++ {
    go func() {
        fmt.Println(i)  // 可能全打印3
    }()
}

// 解决:传递参数
for i := 0; i < 3; i++ {
    go func(n int) {
        fmt.Println(n)  // 打印0, 1, 2
    }(i)
}

循环变量捕获时,闭包引用变量本身而非值,循环结束所有闭包看到最终值。

闭包应用场景

状态保持

Go
func accumulator() func(int) int {
    total := 0
    return func(n int) int {
        total += n
        return total
    }
}

acc := accumulator()
fmt.Println(acc(10))  // 10
fmt.Println(acc(20))  // 30
fmt.Println(acc(30))  // 60

配置封装

Go
func makeGreeter(greeting string) func(string) string {
    return func(name string) string {
        return greeting + name
    }
}

hello := makeGreeter("Hello, ")
hi := makeGreeter("Hi, ")

fmt.Println(hello("Tom"))  // Hello, Tom
fmt.Println(hi("Tom"))     // Hi, Tom

匿名函数与闭包对比

特性匿名函数闭包
定义无名称函数函数 + 外部变量
变量捕获不捕获捕获并持有
状态无状态有状态
多次调用独立执行共享外部变量

要点总结

  • 匿名函数无需命名,可立即调用或赋值
  • 闭包捕获并持有外部变量
  • 闭包多次调用共享同一外部变量
  • 循环中闭包陷阱:引用同一变量
  • 解决闭包陷阱:传递参数而非引用
  • goroutine中闭包同样有陷阱
  • 闭包用于状态保持、配置封装

📝 发现内容有误?点击此处直接编辑

← 上一篇 Go函数定义与声明
下一篇 → Go延迟执行defer
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库