/* 04-closures.go - Go 语言闭包详解 学习目标: 1. 理解闭包的概念和原理 2. 掌握闭包的创建和使用 3. 学会闭包的实际应用场景 4. 了解闭包的内存管理 5. 掌握闭包的最佳实践 知识点: - 闭包的定义和特性 - 词法作用域和变量捕获 - 闭包的生命周期 - 闭包与匿名函数的关系 - 闭包的实际应用模式 - 闭包的性能考虑 */ package main import ( "fmt" "math/rand" "strings" "time" ) func main() { fmt.Println("=== Go 语言闭包详解 ===\n") // 演示闭包的基本概念 demonstrateBasicClosures() // 演示变量捕获 demonstrateVariableCapture() // 演示闭包的状态保持 demonstrateStatefulClosures() // 演示闭包作为返回值 demonstrateClosureReturns() // 演示闭包的实际应用 demonstratePracticalApplications() // 演示闭包的高级用法 demonstrateAdvancedClosureUsage() // 演示闭包的注意事项 demonstrateClosureCaveats() } // demonstrateBasicClosures 演示闭包的基本概念 func demonstrateBasicClosures() { fmt.Println("1. 闭包的基本概念:") // 基本闭包示例 fmt.Printf(" 基本闭包示例:\n") // 外部变量 message := "Hello from closure" // 创建闭包 - 匿名函数访问外部变量 closure := func() { fmt.Printf(" 闭包访问外部变量: %s\n", message) } // 调用闭包 closure() // 修改外部变量 message = "Modified message" closure() // 闭包看到修改后的值 // 闭包修改外部变量 fmt.Printf(" 闭包修改外部变量:\n") counter := 0 increment := func() { counter++ fmt.Printf(" 计数器值: %d\n", counter) } increment() increment() increment() fmt.Printf(" 外部变量 counter 的最终值: %d\n", counter) // 多个闭包共享变量 fmt.Printf(" 多个闭包共享变量:\n") sharedValue := 10 add := func(n int) { sharedValue += n fmt.Printf(" add(%d): sharedValue = %d\n", n, sharedValue) } multiply := func(n int) { sharedValue *= n fmt.Printf(" multiply(%d): sharedValue = %d\n", n, sharedValue) } add(5) // 10 + 5 = 15 multiply(2) // 15 * 2 = 30 add(10) // 30 + 10 = 40 fmt.Println() } // demonstrateVariableCapture 演示变量捕获 func demonstrateVariableCapture() { fmt.Println("2. 变量捕获:") // 值捕获 vs 引用捕获 fmt.Printf(" 值类型变量的捕获:\n") // 创建多个闭包,每个捕获不同的值 var functions []func() for i := 0; i < 3; i++ { // 错误的方式:所有闭包都会捕获同一个变量 i functions = append(functions, func() { fmt.Printf(" 错误方式 - i = %d\n", i) }) } fmt.Printf(" 错误的捕获方式(所有闭包都捕获同一个变量):\n") for _, fn := range functions { fn() // 都会打印 3,因为循环结束后 i = 3 } // 正确的方式:为每个闭包创建独立的变量 functions = nil for i := 0; i < 3; i++ { i := i // 创建新的变量,捕获当前值 functions = append(functions, func() { fmt.Printf(" 正确方式 - i = %d\n", i) }) } fmt.Printf(" 正确的捕获方式(每个闭包捕获独立的变量):\n") for _, fn := range functions { fn() } // 引用类型的捕获 fmt.Printf(" 引用类型变量的捕获:\n") slice := []int{1, 2, 3} modifySlice := func() { slice[0] = 999 fmt.Printf(" 闭包修改切片: %v\n", slice) } fmt.Printf(" 原始切片: %v\n", slice) modifySlice() fmt.Printf(" 外部切片: %v\n", slice) fmt.Println() } // demonstrateStatefulClosures 演示闭包的状态保持 func demonstrateStatefulClosures() { fmt.Println("3. 闭包的状态保持:") // 计数器闭包 fmt.Printf(" 计数器闭包:\n") counter1 := createCounter() counter2 := createCounter() fmt.Printf(" counter1: %d\n", counter1()) fmt.Printf(" counter1: %d\n", counter1()) fmt.Printf(" counter2: %d\n", counter2()) fmt.Printf(" counter1: %d\n", counter1()) fmt.Printf(" counter2: %d\n", counter2()) // 累加器闭包 fmt.Printf(" 累加器闭包:\n") adder := createAdder(10) // 初始值为 10 fmt.Printf(" adder(5): %d\n", adder(5)) // 10 + 5 = 15 fmt.Printf(" adder(3): %d\n", adder(3)) // 15 + 3 = 18 fmt.Printf(" adder(-8): %d\n", adder(-8)) // 18 - 8 = 10 // 银行账户闭包 fmt.Printf(" 银行账户闭包:\n") account := createBankAccount(1000.0) fmt.Printf(" 初始余额: %.2f\n", account.getBalance()) fmt.Printf(" 存款 500: %.2f\n", account.deposit(500)) fmt.Printf(" 取款 200: %.2f\n", account.withdraw(200)) fmt.Printf(" 取款 2000: %.2f\n", account.withdraw(2000)) // 余额不足 // 历史记录闭包 fmt.Printf(" 历史记录闭包:\n") history := createHistory() history.add("用户登录") history.add("查看订单") history.add("添加商品到购物车") history.add("结算订单") fmt.Printf(" 历史记录:\n") for i, record := range history.getAll() { fmt.Printf(" %d. %s\n", i+1, record) } fmt.Printf(" 最近3条记录:\n") for i, record := range history.getLast(3) { fmt.Printf(" %d. %s\n", i+1, record) } fmt.Println() } // demonstrateClosureReturns 演示闭包作为返回值 func demonstrateClosureReturns() { fmt.Println("4. 闭包作为返回值:") // 数学运算闭包工厂 fmt.Printf(" 数学运算闭包工厂:\n") add := createMathOperation("add") multiply := createMathOperation("multiply") power := createMathOperation("power") fmt.Printf(" add(10, 5) = %.2f\n", add(10, 5)) fmt.Printf(" multiply(10, 5) = %.2f\n", multiply(10, 5)) fmt.Printf(" power(2, 8) = %.2f\n", power(2, 8)) // 验证器闭包工厂 fmt.Printf(" 验证器闭包工厂:\n") emailValidator := createValidator("email") phoneValidator := createValidator("phone") ageValidator := createValidator("age") testData := []struct { validator func(string) bool name string values []string }{ {emailValidator, "邮箱", []string{"user@example.com", "invalid-email", "test@domain.org"}}, {phoneValidator, "电话", []string{"138-1234-5678", "123", "186-9999-8888"}}, {ageValidator, "年龄", []string{"25", "abc", "150", "30"}}, } for _, test := range testData { fmt.Printf(" %s验证:\n", test.name) for _, value := range test.values { isValid := test.validator(value) fmt.Printf(" \"%s\": %t\n", value, isValid) } } // 配置闭包工厂 fmt.Printf(" 配置闭包工厂:\n") devConfig := createConfigGetter("development") prodConfig := createConfigGetter("production") fmt.Printf(" 开发环境数据库: %s\n", devConfig("database")) fmt.Printf(" 开发环境端口: %s\n", devConfig("port")) fmt.Printf(" 生产环境数据库: %s\n", prodConfig("database")) fmt.Printf(" 生产环境端口: %s\n", prodConfig("port")) fmt.Println() } // demonstratePracticalApplications 演示闭包的实际应用 func demonstratePracticalApplications() { fmt.Println("5. 闭包的实际应用:") // 应用1: 事件处理器 fmt.Printf(" 应用1 - 事件处理器:\n") button := createButton("提交按钮") // 添加点击事件处理器 button.onClick(func() { fmt.Printf(" 按钮被点击了!\n") }) // 添加多个事件处理器 button.onClick(func() { fmt.Printf(" 记录点击日志\n") }) button.onClick(func() { fmt.Printf(" 发送统计数据\n") }) // 触发点击事件 button.click() // 应用2: 缓存系统 fmt.Printf(" 应用2 - 缓存系统:\n") cache := createCache() // 设置缓存 cache.set("user:123", "Alice") cache.set("user:456", "Bob") // 获取缓存 if value, found := cache.get("user:123"); found { fmt.Printf(" 缓存命中: user:123 = %s\n", value) } if value, found := cache.get("user:789"); found { fmt.Printf(" 缓存命中: user:789 = %s\n", value) } else { fmt.Printf(" 缓存未命中: user:789\n") } // 显示缓存统计 stats := cache.getStats() fmt.Printf(" 缓存统计: 命中 %d 次,未命中 %d 次\n", stats.hits, stats.misses) // 应用3: 中间件模式 fmt.Printf(" 应用3 - 中间件模式:\n") // 创建处理器 handler := func(request string) string { return fmt.Sprintf("处理请求: %s", request) } // 应用中间件 withLogging := loggingMiddleware(handler) withAuth := authMiddleware(withLogging) withRateLimit := rateLimitMiddleware(withAuth) // 处理请求 result := withRateLimit("GET /api/users") fmt.Printf(" 最终结果: %s\n", result) // 应用4: 函数式编程 fmt.Printf(" 应用4 - 函数式编程:\n") numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} // 使用闭包进行函数式操作 evenNumbers := filter(numbers, func(n int) bool { return n%2 == 0 }) fmt.Printf(" 偶数: %v\n", evenNumbers) squares := mapInts(numbers, func(n int) int { return n * n }) fmt.Printf(" 平方: %v\n", squares) sum := reduce(numbers, 0, func(acc, n int) int { return acc + n }) fmt.Printf(" 求和: %d\n", sum) // 应用5: 延迟执行 fmt.Printf(" 应用5 - 延迟执行:\n") // 创建延迟任务 task1 := createDelayedTask("任务1", func() { fmt.Printf(" 执行任务1: 发送邮件\n") }) task2 := createDelayedTask("任务2", func() { fmt.Printf(" 执行任务2: 清理缓存\n") }) // 延迟执行 fmt.Printf(" 创建延迟任务...\n") time.Sleep(100 * time.Millisecond) task1.execute() task2.execute() fmt.Println() } // demonstrateAdvancedClosureUsage 演示闭包的高级用法 func demonstrateAdvancedClosureUsage() { fmt.Println("6. 闭包的高级用法:") // 高级用法1: 柯里化 fmt.Printf(" 高级用法1 - 柯里化:\n") // 创建柯里化的加法函数 curriedAdd := curry(func(a, b, c int) int { return a + b + c }) // 部分应用 add5 := curriedAdd(5) add5And3 := add5(3) result := add5And3(2) // 5 + 3 + 2 = 10 fmt.Printf(" 柯里化结果: 5 + 3 + 2 = %d\n", result) // 高级用法2: 记忆化 fmt.Printf(" 高级用法2 - 记忆化:\n") // 创建记忆化的斐波那契函数 memoFib := memoize(fibonacci) fmt.Printf(" 计算斐波那契数列:\n") for i := 0; i <= 10; i++ { result := memoFib(i) fmt.Printf(" fib(%d) = %d\n", i, result) } // 高级用法3: 装饰器模式 fmt.Printf(" 高级用法3 - 装饰器模式:\n") // 原始函数 slowFunction := func(n int) int { time.Sleep(10 * time.Millisecond) // 模拟慢操作 return n * n } // 应用装饰器 timedFunction := withTiming(slowFunction) cachedFunction := withCaching(timedFunction) fmt.Printf(" 第一次调用:\n") result1 := cachedFunction(5) fmt.Printf(" 结果: %d\n", result1) fmt.Printf(" 第二次调用(应该使用缓存):\n") result2 := cachedFunction(5) fmt.Printf(" 结果: %d\n", result2) // 高级用法4: 状态机 fmt.Printf(" 高级用法4 - 状态机:\n") fsm := createStateMachine() fmt.Printf(" 当前状态: %s\n", fsm.getState()) fsm.start() fmt.Printf(" 当前状态: %s\n", fsm.getState()) fsm.pause() fmt.Printf(" 当前状态: %s\n", fsm.getState()) fsm.resume() fmt.Printf(" 当前状态: %s\n", fsm.getState()) fsm.stop() fmt.Printf(" 当前状态: %s\n", fsm.getState()) // 高级用法5: 观察者模式 fmt.Printf(" 高级用法5 - 观察者模式:\n") subject := createSubject() // 添加观察者 subject.subscribe(func(data interface{}) { fmt.Printf(" 观察者1收到数据: %v\n", data) }) subject.subscribe(func(data interface{}) { fmt.Printf(" 观察者2收到数据: %v\n", data) }) // 通知观察者 subject.notify("Hello, Observers!") subject.notify(42) fmt.Println() } // demonstrateClosureCaveats 演示闭包的注意事项 func demonstrateClosureCaveats() { fmt.Println("7. 闭包的注意事项:") // 注意事项1: 循环变量捕获 fmt.Printf(" 注意事项1 - 循环变量捕获:\n") fmt.Printf(" 这是一个常见的陷阱,前面已经演示过\n") // 注意事项2: 内存泄漏 fmt.Printf(" 注意事项2 - 内存泄漏风险:\n") fmt.Printf(" 闭包会保持对外部变量的引用,可能导致内存泄漏\n") // 创建一个可能导致内存泄漏的示例 largeData := make([]int, 1000000) // 大数组 for i := range largeData { largeData[i] = i } // 闭包只使用数组的第一个元素,但会保持整个数组的引用 getClosure := func() func() int { return func() int { return largeData[0] // 只使用第一个元素 } } closure := getClosure() fmt.Printf(" 闭包结果: %d\n", closure()) fmt.Printf(" 注意: 闭包保持了整个大数组的引用\n") // 更好的做法:只捕获需要的数据 getBetterClosure := func() func() int { firstElement := largeData[0] // 只捕获需要的值 return func() int { return firstElement } } betterClosure := getBetterClosure() fmt.Printf(" 改进的闭包结果: %d\n", betterClosure()) fmt.Printf(" 改进: 只捕获需要的值,不保持大数组引用\n") // 注意事项3: 性能考虑 fmt.Printf(" 注意事项3 - 性能考虑:\n") fmt.Printf(" 闭包的创建和调用有一定的性能开销\n") // 测量闭包 vs 普通函数的性能 normalFunc := func(x int) int { return x * 2 } multiplier := 2 closureFunc := func(x int) int { return x * multiplier } // 简单的性能比较(实际测试需要更严格的基准测试) start := time.Now() for i := 0; i < 1000000; i++ { normalFunc(i) } normalTime := time.Since(start) start = time.Now() for i := 0; i < 1000000; i++ { closureFunc(i) } closureTime := time.Since(start) fmt.Printf(" 普通函数耗时: %v\n", normalTime) fmt.Printf(" 闭包函数耗时: %v\n", closureTime) // 最佳实践 fmt.Printf(" 最佳实践:\n") fmt.Printf(" 1. 避免在循环中直接使用循环变量创建闭包\n") fmt.Printf(" 2. 只捕获必要的变量,避免捕获大对象\n") fmt.Printf(" 3. 注意闭包的生命周期,避免内存泄漏\n") fmt.Printf(" 4. 在性能敏感的代码中谨慎使用闭包\n") fmt.Printf(" 5. 使用闭包实现优雅的设计模式\n") fmt.Println() } // ========== 函数定义 ========== // 基本闭包函数 func createCounter() func() int { count := 0 return func() int { count++ return count } } func createAdder(initial int) func(int) int { sum := initial return func(n int) int { sum += n return sum } } // 银行账户闭包 type BankAccount struct { getBalance func() float64 deposit func(float64) float64 withdraw func(float64) float64 } func createBankAccount(initialBalance float64) BankAccount { balance := initialBalance return BankAccount{ getBalance: func() float64 { return balance }, deposit: func(amount float64) float64 { if amount > 0 { balance += amount } return balance }, withdraw: func(amount float64) float64 { if amount > 0 && amount <= balance { balance -= amount } return balance }, } } // 历史记录闭包 type History struct { add func(string) getAll func() []string getLast func(int) []string } func createHistory() History { var records []string return History{ add: func(record string) { records = append(records, record) }, getAll: func() []string { result := make([]string, len(records)) copy(result, records) return result }, getLast: func(n int) []string { if n >= len(records) { result := make([]string, len(records)) copy(result, records) return result } result := make([]string, n) copy(result, records[len(records)-n:]) return result }, } } // 数学运算闭包工厂 func createMathOperation(operation string) func(float64, float64) float64 { switch operation { case "add": return func(a, b float64) float64 { return a + b } case "subtract": return func(a, b float64) float64 { return a - b } case "multiply": return func(a, b float64) float64 { return a * b } case "divide": return func(a, b float64) float64 { if b != 0 { return a / b } return 0 } case "power": return func(a, b float64) float64 { result := 1.0 for i := 0; i < int(b); i++ { result *= a } return result } default: return func(a, b float64) float64 { return 0 } } } // 验证器闭包工厂 func createValidator(validationType string) func(string) bool { switch validationType { case "email": return func(email string) bool { return len(email) > 0 && strings.Contains(email, "@") && strings.Contains(email, ".") } case "phone": return func(phone string) bool { return len(phone) >= 10 && strings.Contains(phone, "-") } case "age": return func(ageStr string) bool { // 简单验证:只检查是否为数字 for _, char := range ageStr { if char < '0' || char > '9' { return false } } return len(ageStr) > 0 } default: return func(string) bool { return false } } } // 配置闭包工厂 func createConfigGetter(environment string) func(string) string { configs := map[string]map[string]string{ "development": { "database": "localhost:5432", "port": "8080", "debug": "true", }, "production": { "database": "prod-db:5432", "port": "80", "debug": "false", }, } envConfig := configs[environment] return func(key string) string { if value, exists := envConfig[key]; exists { return value } return "" } } // 事件处理器 type Button struct { name string handlers []func() } func createButton(name string) *Button { return &Button{name: name} } func (b *Button) onClick(handler func()) { b.handlers = append(b.handlers, handler) } func (b *Button) click() { fmt.Printf(" 点击按钮: %s\n", b.name) for _, handler := range b.handlers { handler() } } // 缓存系统 type Cache struct { set func(string, string) get func(string) (string, bool) getStats func() struct{ hits, misses int } } func createCache() Cache { data := make(map[string]string) hits := 0 misses := 0 return Cache{ set: func(key, value string) { data[key] = value }, get: func(key string) (string, bool) { if value, exists := data[key]; exists { hits++ return value, true } misses++ return "", false }, getStats: func() struct{ hits, misses int } { return struct{ hits, misses int }{hits, misses} }, } } // 中间件模式 func loggingMiddleware(next func(string) string) func(string) string { return func(request string) string { fmt.Printf(" [LOG] 处理请求: %s\n", request) result := next(request) fmt.Printf(" [LOG] 请求完成: %s\n", request) return result } } func authMiddleware(next func(string) string) func(string) string { return func(request string) string { fmt.Printf(" [AUTH] 验证请求: %s\n", request) // 模拟认证 if strings.Contains(request, "GET") { return next(request) } return "认证失败" } } func rateLimitMiddleware(next func(string) string) func(string) string { requestCount := 0 return func(request string) string { requestCount++ fmt.Printf(" [RATE] 请求计数: %d\n", requestCount) if requestCount > 10 { return "请求过于频繁" } return next(request) } } // 函数式编程辅助函数 func filter(slice []int, predicate func(int) bool) []int { var result []int for _, item := range slice { if predicate(item) { result = append(result, item) } } return result } func mapInts(slice []int, mapper func(int) int) []int { result := make([]int, len(slice)) for i, item := range slice { result[i] = mapper(item) } return result } func reduce(slice []int, initial int, reducer func(int, int) int) int { result := initial for _, item := range slice { result = reducer(result, item) } return result } // 延迟执行 type DelayedTask struct { name string task func() execute func() } func createDelayedTask(name string, task func()) DelayedTask { return DelayedTask{ name: name, task: task, execute: func() { fmt.Printf(" 准备执行延迟任务: %s\n", name) task() }, } } // 柯里化 func curry(fn func(int, int, int) int) func(int) func(int) func(int) int { return func(a int) func(int) func(int) int { return func(b int) func(int) int { return func(c int) int { return fn(a, b, c) } } } } // 记忆化 func memoize(fn func(int) int) func(int) int { cache := make(map[int]int) return func(n int) int { if result, exists := cache[n]; exists { return result } result := fn(n) cache[n] = result return result } } func fibonacci(n int) int { if n <= 1 { return n } return fibonacci(n-1) + fibonacci(n-2) } // 装饰器模式 func withTiming(fn func(int) int) func(int) int { return func(n int) int { start := time.Now() result := fn(n) duration := time.Since(start) fmt.Printf(" 函数执行耗时: %v\n", duration) return result } } func withCaching(fn func(int) int) func(int) int { cache := make(map[int]int) return func(n int) int { if result, exists := cache[n]; exists { fmt.Printf(" 使用缓存结果\n") return result } fmt.Printf(" 计算新结果\n") result := fn(n) cache[n] = result return result } } // 状态机 type StateMachine struct { getState func() string start func() pause func() resume func() stop func() } func createStateMachine() StateMachine { state := "idle" return StateMachine{ getState: func() string { return state }, start: func() { if state == "idle" { state = "running" } }, pause: func() { if state == "running" { state = "paused" } }, resume: func() { if state == "paused" { state = "running" } }, stop: func() { if state == "running" || state == "paused" { state = "idle" } }, } } // 观察者模式 type Subject struct { subscribe func(func(interface{})) notify func(interface{}) } func createSubject() Subject { var observers []func(interface{}) return Subject{ subscribe: func(observer func(interface{})) { observers = append(observers, observer) }, notify: func(data interface{}) { for _, observer := range observers { observer(data) } }, } } func init() { rand.Seed(time.Now().UnixNano()) } /* 运行这个程序: go run 04-closures.go 学习要点: 1. 闭包是函数和其词法环境的组合 2. 闭包可以访问和修改外部作用域的变量 3. 闭包可以保持状态,实现数据封装 4. 闭包常用于回调函数、事件处理、函数式编程 5. 需要注意循环变量捕获和内存泄漏问题 闭包的特性: 1. 词法作用域:闭包可以访问定义时的作用域 2. 变量捕获:闭包会捕获外部变量的引用 3. 状态保持:闭包可以在多次调用间保持状态 4. 延迟执行:闭包可以延迟执行代码 常见应用场景: 1. 事件处理和回调函数 2. 函数式编程(map、filter、reduce) 3. 中间件和装饰器模式 4. 状态管理和数据封装 5. 配置和选项处理 6. 缓存和记忆化 7. 延迟执行和任务调度 设计模式: 1. 工厂模式:返回配置好的闭包 2. 装饰器模式:包装函数添加功能 3. 观察者模式:事件处理和通知 4. 状态机模式:状态管理 5. 策略模式:动态选择算法 最佳实践: 1. 避免在循环中直接捕获循环变量 2. 只捕获必要的变量,避免内存泄漏 3. 合理使用闭包实现优雅的API设计 4. 注意闭包的性能开销 5. 使用闭包实现函数式编程风格 注意事项: 1. 循环变量捕获陷阱 2. 内存泄漏风险 3. 性能开销 4. 调试困难 5. 代码可读性 高级用法: 1. 柯里化和部分应用 2. 记忆化优化 3. 函数组合和管道 4. 异步编程模式 5. 依赖注入 */