匿名函数和闭包是 Go 语言函数式编程的重要特性。本章将详细介绍它们的概念和使用方法。
匿名函数是没有名称的函数,也称为函数字面量。
package main
import "fmt"
func main() {
add := func(a, b int) int {
return a + b
}
result := add(10, 20)
fmt.Printf("结果: %d\n", result)
}
package main
import "fmt"
func main() {
result := func(a, b int) int {
return a + b
}(10, 20)
fmt.Printf("结果: %d\n", result)
}
package main
import "fmt"
func process(nums []int, f func(int) int) []int {
result := make([]int, len(nums))
for i, num := range nums {
result[i] = f(num)
}
return result
}
func main() {
nums := []int{1, 2, 3, 4, 5}
doubled := process(nums, func(n int) int {
return n * 2
})
fmt.Printf("翻倍: %v\n", doubled)
squared := process(nums, func(n int) int {
return n * n
})
fmt.Printf("平方: %v\n", squared)
}
闭包是一个函数值,它引用了其外部作用域中的变量。闭包可以访问和修改外部变量。
package main
import "fmt"
func main() {
x := 10
f := func() {
fmt.Printf("x = %d\n", x)
}
f()
}
package main
import "fmt"
func main() {
counter := 0
increment := func() int {
counter++
return counter
}
fmt.Println(increment())
fmt.Println(increment())
fmt.Println(increment())
}
输出:
1
2
3
package main
import "fmt"
func counter() func() int {
count := 0
return func() int {
count++
return count
}
}
func main() {
c1 := counter()
fmt.Println(c1())
fmt.Println(c1())
fmt.Println(c1())
c2 := counter()
fmt.Println(c2())
}
输出:
1
2
3
1
package main
import "fmt"
func newCounter() func() int {
count := 0
return func() int {
count++
return count
}
}
func main() {
counter := newCounter()
for i := 0; i < 5; i++ {
fmt.Printf("调用 %d 次\n", counter())
}
}
package main
import "fmt"
func fibonacci() func() int {
a, b := 0, 1
return func() int {
a, b = b, a+b
return a
}
}
func main() {
f := fibonacci()
for i := 0; i < 10; i++ {
fmt.Printf("%d ", f())
}
}
输出:
1 1 2 3 5 8 13 21 34 55
package main
import "fmt"
func memoize(f func(int) int) func(int) int {
cache := make(map[int]int)
return func(n int) int {
if v, ok := cache[n]; ok {
fmt.Printf("从缓存获取: %d\n", n)
return v
}
result := f(n)
cache[n] = result
fmt.Printf("计算并缓存: %d\n", n)
return result
}
}
func slowSquare(n int) int {
return n * n
}
func main() {
fastSquare := memoize(slowSquare)
fmt.Println(fastSquare(5))
fmt.Println(fastSquare(5))
fmt.Println(fastSquare(10))
fmt.Println(fastSquare(10))
}
package main
import "fmt"
func processWithCallback(data []int, callback func(int)) {
for _, item := range data {
callback(item)
}
}
func main() {
nums := []int{1, 2, 3, 4, 5}
fmt.Println("打印每个元素:")
processWithCallback(nums, func(n int) {
fmt.Printf("%d ", n)
})
fmt.Println()
fmt.Println("\n打印平方:")
processWithCallback(nums, func(n int) {
fmt.Printf("%d ", n*n)
})
fmt.Println()
}
package main
import (
"fmt"
"time"
)
func main() {
for i := 0; i < 3; i++ {
go func() {
fmt.Printf("i = %d\n", i)
}()
}
time.Sleep(time.Second)
}
输出可能:
i = 3
i = 3
i = 3
解决方法:传递参数
package main
import (
"fmt"
"time"
)
func main() {
for i := 0; i < 3; i++ {
go func(n int) {
fmt.Printf("n = %d\n", n)
}(i)
}
time.Sleep(time.Second)
}
输出:
n = 0
n = 1
n = 2
本章学习了 Go 语言的匿名函数和闭包:
| 知识点 | 说明 |
|---|---|
| 匿名函数 | 没有名称的函数 |
| 立即执行 | func(){...}() |
| 闭包 | 引用外部变量的函数 |
| 应用场景 | 计数器、缓存、回调等 |
| 循环陷阱 | 循环变量共享问题 |