文章目录
- [🚀 08 - Go 函数(中):匿名函数、闭包与函数式编程](#🚀 08 - Go 函数(中):匿名函数、闭包与函数式编程)
- [匿名函数(Anonymous Function)](#匿名函数(Anonymous Function))
- 函数是一等公民(重点理解)
- 函数作为参数
- 函数作为返回值
- 闭包(Closure)🔥面试重点
- [defer 机制基础(必考🔥)](#defer 机制基础(必考🔥))
-
- [defer 是什么?](#defer 是什么?)
- [多个 defer 执行顺序](#多个 defer 执行顺序)
- [defer 常见使用场景](#defer 常见使用场景)
-
- [📌 资源释放](#📌 资源释放)
- [📌 解锁](#📌 解锁)
- 小结(建议收藏⭐)
- [🎯 最后说一句](#🎯 最后说一句)
- [🚀 下一篇预告(强烈建议继续看)](#🚀 下一篇预告(强烈建议继续看))
🚀 08 - Go 函数(中):匿名函数、闭包与函数式编程
在上一篇中,我们已经掌握了 Go 函数的基础用法(定义、参数、返回值等)。
但如果只停留在基础,其实还远远不够应对实际开发和面试。
这一篇,我们进入真正的"进阶核心":
👉 匿名函数
👉 闭包(面试高频🔥)
👉 函数作为一等公民
👉 defer 机制基础
这些内容,是拉开 Go 水平差距的关键
匿名函数(Anonymous Function)
什么是匿名函数?
👉 没有函数名的函数
go
func() {
fmt.Println("hello")
}
立即执行函数(IIFE)
go
package main
import "fmt"
func main() {
func() {
fmt.Println("hello world")
}()
}
输出:
bath
Hello, World!
👉 特点:
- 定义后立即执行
- 常用于临时逻辑
匿名函数赋值给变量
go
package main
import "fmt"
func main() {
add := func(a, b int) int {
return a + b
}
fmt.Println(add(10, 20))
}
输出:
bath
30
👉 本质:
- 函数可以像变量一样使用
函数是一等公民(重点理解)
在 Go 中,函数可以:
- 赋值给变量 ✅
- 作为参数传递 ✅
- 作为返回值返回 ✅
👉 这就是"函数式编程"的基础
函数作为参数
go
package main
import "fmt"
// 这里演示了如何使用函数作为参数传递
func calc(a, b int, op func(int, int) int) int {
return op(a, b)
}
func add(a, b int) int {
return a + b
}
func main() {
res := calc(10, 20, add)
fmt.Println(res)
fmt.Println(add(2, 3))
}
输出:
bath
30
5
👉 使用匿名函数:
go
package main
import "fmt"
func calc(a, b int, op func(int, int) int) int {
return op(a, b)
}
// 匿名函数作为参数传递
func main() {
res := calc(10, 20, func(a, b int) int {
return a * b
})
fmt.Println(res)
}
输出:
bath
200
📌 使用场景:
- 策略模式
- 回调函数
- 中间件设计
函数作为返回值
go
package main
import "fmt"
func choose(op string) func(int, int) int {
if op == "+" {
return func(a, b int) int {
return a + b
}
}
if op == "-" {
return func(a, b int) int {
return a - b
}
}
// 就是没有匹配上+ - 这两个操作符,就直接a,b 直接返回a和b数值即可
return func(a, b int) int {
fmt.Println("没有匹配到操作符")
fmt.Println(a, b)
return 0
}
}
func main() {
f := choose("*")
fmt.Println(f(10, 5))
}
输出:
bath
没有匹配到操作符
10 5
0
👉 场景:
- 工厂模式
- 动态逻辑选择
闭包(Closure)🔥面试重点
什么是闭包?
👉 函数 + 外部变量 = 闭包
示例:计数器
go
package main
import "fmt"
func counter() func() int {
i := 0
return func() int {
i++
return i
}
}
func add(a int) int {
i := a
i++
return i
}
func main() {
c := counter()
fmt.Println(c()) // 1
fmt.Println(c()) // 2
fmt.Println(c()) // 3
// 下边这个是作对比的
fmt.Println(add(5))
fmt.Println(add(6))
fmt.Println(add(7))
}
输出:
bath
1
2
3
6
7
8
为什么能"记住变量"?
👉 因为:
i并没有被销毁- 被内部函数"引用"住了
- 生命周期被延长
📌 本质理解:
闭包 = 捕获外部变量的函数
闭包的实际应用
状态保存
go
package main
import "fmt"
func accumulator(base int) func(int) int {
return func(x int) int {
base += x
return base
}
}
func main() {
acc := accumulator(10)
fmt.Println(acc(5)) // 输出: 15
fmt.Println(acc(3)) // 输出: 18
fmt.Println(acc(2)) // 输出: 20
}
权限/配置封装
👉 在中间件、限流器中非常常见
defer 机制基础(必考🔥)
defer 是什么?
👉 用于"延迟执行"
go
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println(time.Now().Format("2006-01-02 15:04:05.0000000"))
defer fmt.Println("world")
fmt.Println("hello")
fmt.Println(time.Now().Format("2006-01-02 15:04:05.0000000"))
}
输出:
bath
2026-04-13 22:13:34.0237855
hello
2026-04-13 22:13:34.0240836
world
多个 defer 执行顺序
go
package main
import (
"fmt"
)
func main() {
defer fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)
}
输出:
bath
3
2
1
👉 结论:
- defer 是后进先出(栈)
defer 常见使用场景
📌 资源释放
go
file, _ := os.Open("test.txt")
defer file.Close()
📌 解锁
go
mu.Lock()
defer mu.Unlock()
👉 优点:
- 防止忘记释放资源
- 代码更安全
小结(建议收藏⭐)
这一篇,我们掌握了 Go 函数的核心进阶能力:
✅ 匿名函数(立即执行 / 赋值)
✅ 函数是一等公民(参数 / 返回值)
✅ 闭包(核心重点🔥)
✅ defer 延迟执行机制
✅ 常见使用场景(资源释放 / 回调 / 封装逻辑)
🎯 最后说一句
如果说第一篇是"基础",那这一篇就是:
👉 真正进入 Go 编程思维的关键
因为:
- 闭包 → 用于封装状态
- 函数传递 → 用于解耦逻辑
- defer → 用于资源管理
这些都是写工程代码必须掌握的能力
🚀 下一篇预告(强烈建议继续看)
👉 深入理解 Go 函数(下):defer 执行时机、值传递陷阱与经典面试坑
会带你解决:
- defer 为什么有时候"坑你"
- range + 闭包为什么会出 bug
- slice / map 传参到底怎么回事