Go学习笔记-Functions

函数是Go语言的核心构建块。Go函数支持多返回值、命名返回值、可变参数、闭包等特性,使得代码更加灵活和强大。

基本函数定义

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package main

import "fmt"

// 1. 基本函数定义
func greet() {
    fmt.Println("Hello, World!")
}

// 2. 带参数的函数
func greetPerson(name string) {
    fmt.Printf("Hello, %s!\n", name)
}

// 3. 带返回值的函数
func add(a, b int) int {
    return a + b
}

// 4. 多个参数,相同类型可以简写
func multiply(a, b, c int) int {
    return a * b * c
}

// 5. 多返回值函数
func divmod(a, b int) (int, int) {
    return a / b, a % b
}

// 6. 命名返回值
func calculate(a, b int) (sum, product int) {
    sum = a + b
    product = a * b
    return  // 裸返回,返回命名的返回值
}

func main() {
    // 调用无参数函数
    greet()
    
    // 调用带参数函数
    greetPerson("Go")
    
    // 调用带返回值函数
    result := add(10, 20)
    fmt.Printf("10 + 20 = %d\n", result)
    
    // 调用多参数函数
    product := multiply(2, 3, 4)
    fmt.Printf("2 * 3 * 4 = %d\n", product)
    
    // 调用多返回值函数
    quotient, remainder := divmod(17, 5)
    fmt.Printf("17 ÷ 5 = %d 余 %d\n", quotient, remainder)
    
    // 忽略某些返回值
    q, _ := divmod(20, 3)
    fmt.Printf("20 ÷ 3 = %d\n", q)
    
    // 调用命名返回值函数
    s, p := calculate(5, 6)
    fmt.Printf("5 + 6 = %d, 5 * 6 = %d\n", s, p)
}

可变参数函数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package main

import "fmt"

// 1. 可变参数函数
func sum(numbers ...int) int {
    total := 0
    for _, num := range numbers {
        total += num
    }
    return total
}

// 2. 混合参数(固定参数 + 可变参数)
func greetAll(greeting string, names ...string) {
    for _, name := range names {
        fmt.Printf("%s, %s!\n", greeting, name)
    }
}

// 3. 空接口可变参数(接受任意类型)
func printAll(values ...interface{}) {
    for i, value := range values {
        fmt.Printf("参数%d: %v (类型: %T)\n", i, value, value)
    }
}

// 4. 传递切片给可变参数函数
func processNumbers(operation string, numbers ...int) {
    fmt.Printf("操作: %s\n", operation)
    switch operation {
    case "sum":
        fmt.Printf("总和: %d\n", sum(numbers...))
    case "max":
        if len(numbers) > 0 {
            max := numbers[0]
            for _, num := range numbers[1:] {
                if num > max {
                    max = num
                }
            }
            fmt.Printf("最大值: %d\n", max)
        }
    case "min":
        if len(numbers) > 0 {
            min := numbers[0]
            for _, num := range numbers[1:] {
                if num < min {
                    min = num
                }
            }
            fmt.Printf("最小值: %d\n", min)
        }
    }
}

func main() {
    // 调用可变参数函数
    fmt.Printf("sum() = %d\n", sum())
    fmt.Printf("sum(1) = %d\n", sum(1))
    fmt.Printf("sum(1, 2, 3) = %d\n", sum(1, 2, 3))
    fmt.Printf("sum(1, 2, 3, 4, 5) = %d\n", sum(1, 2, 3, 4, 5))
    
    // 混合参数函数
    greetAll("Hello", "Alice", "Bob", "Charlie")
    
    // 空接口可变参数
    printAll(42, "hello", true, 3.14, []int{1, 2, 3})
    
    // 传递切片给可变参数函数
    numbers := []int{10, 5, 8, 3, 9, 1}
    processNumbers("sum", numbers...)
    processNumbers("max", numbers...)
    processNumbers("min", numbers...)
    
    // 直接传递参数
    processNumbers("sum", 1, 2, 3, 4, 5)
}

函数作为值

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
package main

import "fmt"

// 定义函数类型
type Operation func(int, int) int

// 具体的操作函数
func add(a, b int) int {
    return a + b
}

func subtract(a, b int) int {
    return a - b
}

func multiply(a, b int) int {
    return a * b
}

func divide(a, b int) int {
    if b != 0 {
        return a / b
    }
    return 0
}

// 高阶函数:接受函数作为参数
func calculate(a, b int, op Operation) int {
    return op(a, b)
}

// 返回函数的函数
func getOperation(opType string) Operation {
    switch opType {
    case "add":
        return add
    case "subtract":
        return subtract
    case "multiply":
        return multiply
    case "divide":
        return divide
    default:
        return nil
    }
}

// 函数切片
func applyOperations(a, b int, operations []Operation) []int {
    results := make([]int, len(operations))
    for i, op := range operations {
        results[i] = op(a, b)
    }
    return results
}

func main() {
    // 1. 将函数赋值给变量
    var op Operation = add
    result := op(10, 5)
    fmt.Printf("使用函数变量: %d\n", result)
    
    // 2. 使用高阶函数
    fmt.Printf("calculate(10, 5, add): %d\n", calculate(10, 5, add))
    fmt.Printf("calculate(10, 5, subtract): %d\n", calculate(10, 5, subtract))
    fmt.Printf("calculate(10, 5, multiply): %d\n", calculate(10, 5, multiply))
    
    // 3. 从函数获取函数
    addOp := getOperation("add")
    if addOp != nil {
        fmt.Printf("动态获取的加法函数: %d\n", addOp(15, 25))
    }
    
    // 4. 匿名函数
    square := func(x int) int {
        return x * x
    }
    fmt.Printf("匿名函数计算平方: %d\n", square(7))
    
    // 5. 立即执行的匿名函数
    result = func(a, b int) int {
        return a*a + b*b
    }(3, 4)
    fmt.Printf("立即执行的匿名函数: %d\n", result)
    
    // 6. 函数切片
    operations := []Operation{add, subtract, multiply, divide}
    results := applyOperations(12, 3, operations)
    fmt.Printf("批量操作结果: %v\n", results)
    
    // 7. 函数映射
    opMap := map[string]Operation{
        "+": add,
        "-": subtract,
        "*": multiply,
        "/": divide,
    }
    
    if op, exists := opMap["*"]; exists {
        fmt.Printf("从映射获取乘法函数: %d\n", op(6, 7))
    }
}

闭包

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package main

import "fmt"

// 1. 基本闭包
func makeCounter() func() int {
    count := 0
    return func() int {
        count++
        return count
    }
}

// 2. 带参数的闭包工厂
func makeAdder(x int) func(int) int {
    return func(y int) int {
        return x + y
    }
}

// 3. 闭包修改外部变量
func makeAccumulator() func(int) int {
    sum := 0
    return func(value int) int {
        sum += value
        return sum
    }
}

// 4. 多个闭包共享状态
func makeCounterPair() (func() int, func() int) {
    count := 0
    increment := func() int {
        count++
        return count
    }
    decrement := func() int {
        count--
        return count
    }
    return increment, decrement
}

// 5. 闭包捕获循环变量的陷阱和解决方案
func createFunctions() []func() int {
    var functions []func() int
    
    // 错误的方式:所有闭包都会捕获同一个变量
    for i := 0; i < 3; i++ {
        // 错误:所有函数都会返回3
        // functions = append(functions, func() int { return i })
        
        // 正确的方式1:使用局部变量
        j := i
        functions = append(functions, func() int { return j })
    }
    
    return functions
}

// 6. 闭包作为回调函数
func processData(data []int, callback func(int) int) []int {
    result := make([]int, len(data))
    for i, value := range data {
        result[i] = callback(value)
    }
    return result
}

func main() {
    // 1. 基本闭包使用
    counter1 := makeCounter()
    counter2 := makeCounter()
    
    fmt.Printf("counter1: %d\n", counter1()) // 1
    fmt.Printf("counter1: %d\n", counter1()) // 2
    fmt.Printf("counter2: %d\n", counter2()) // 1
    fmt.Printf("counter1: %d\n", counter1()) // 3
    
    // 2. 带参数的闭包
    add5 := makeAdder(5)
    add10 := makeAdder(10)
    
    fmt.Printf("add5(3): %d\n", add5(3))   // 8
    fmt.Printf("add10(3): %d\n", add10(3)) // 13
    
    // 3. 累加器闭包
    acc := makeAccumulator()
    fmt.Printf("累加5: %d\n", acc(5))   // 5
    fmt.Printf("累加3: %d\n", acc(3))   // 8
    fmt.Printf("累加7: %d\n", acc(7))   // 15
    
    // 4. 共享状态的闭包
    inc, dec := makeCounterPair()
    fmt.Printf("increment: %d\n", inc()) // 1
    fmt.Printf("increment: %d\n", inc()) // 2
    fmt.Printf("decrement: %d\n", dec()) // 1
    fmt.Printf("increment: %d\n", inc()) // 2
    
    // 5. 闭包捕获循环变量
    functions := createFunctions()
    for i, fn := range functions {
        fmt.Printf("function[%d](): %d\n", i, fn())
    }
    
    // 6. 闭包作为回调函数
    data := []int{1, 2, 3, 4, 5}
    
    // 平方操作
    squared := processData(data, func(x int) int {
        return x * x
    })
    fmt.Printf("平方: %v\n", squared)
    
    // 乘以2操作
    doubled := processData(data, func(x int) int {
        return x * 2
    })
    fmt.Printf("乘以2: %v\n", doubled)
    
    // 使用闭包捕获外部变量
    multiplier := 3
    tripled := processData(data, func(x int) int {
        return x * multiplier
    })
    fmt.Printf("乘以%d: %v\n", multiplier, tripled)
}

递归函数

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
package main

import "fmt"

// 1. 阶乘函数
func factorial(n int) int {
    if n <= 1 {
        return 1
    }
    return n * factorial(n-1)
}

// 2. 斐波那契数列
func fibonacci(n int) int {
    if n <= 1 {
        return n
    }
    return fibonacci(n-1) + fibonacci(n-2)
}

// 3. 带记忆化的斐波那契数列
func fibonacciMemo(n int, memo map[int]int) int {
    if n <= 1 {
        return n
    }
    
    if val, exists := memo[n]; exists {
        return val
    }
    
    memo[n] = fibonacciMemo(n-1, memo) + fibonacciMemo(n-2, memo)
    return memo[n]
}

// 4. 二分查找
func binarySearch(arr []int, target, left, right int) int {
    if left > right {
        return -1
    }
    
    mid := left + (right-left)/2
    
    if arr[mid] == target {
        return mid
    } else if arr[mid] > target {
        return binarySearch(arr, target, left, mid-1)
    } else {
        return binarySearch(arr, target, mid+1, right)
    }
}

// 5. 树形结构遍历
type TreeNode struct {
    Value int
    Left  *TreeNode
    Right *TreeNode
}

func (node *TreeNode) inorderTraversal() {
    if node != nil {
        node.Left.inorderTraversal()
        fmt.Printf("%d ", node.Value)
        node.Right.inorderTraversal()
    }
}

// 6. 汉诺塔问题
func hanoi(n int, from, to, aux string) {
    if n == 1 {
        fmt.Printf("移动盘子从 %s 到 %s\n", from, to)
        return
    }
    
    hanoi(n-1, from, aux, to)
    fmt.Printf("移动盘子从 %s 到 %s\n", from, to)
    hanoi(n-1, aux, to, from)
}

// 7. 目录遍历模拟
type Directory struct {
    Name        string
    Files       []string
    Directories []*Directory
}

func (dir *Directory) printStructure(indent string) {
    fmt.Printf("%s%s/\n", indent, dir.Name)
    
    for _, file := range dir.Files {
        fmt.Printf("%s  %s\n", indent, file)
    }
    
    for _, subDir := range dir.Directories {
        subDir.printStructure(indent + "  ")
    }
}

func main() {
    // 1. 阶乘
    fmt.Println("阶乘:")
    for i := 0; i <= 5; i++ {
        fmt.Printf("%d! = %d\n", i, factorial(i))
    }
    
    // 2. 斐波那契数列
    fmt.Println("\n斐波那契数列:")
    for i := 0; i <= 10; i++ {
        fmt.Printf("fib(%d) = %d\n", i, fibonacci(i))
    }
    
    // 3. 带记忆化的斐波那契数列
    fmt.Println("\n带记忆化的斐波那契数列:")
    memo := make(map[int]int)
    for i := 0; i <= 10; i++ {
        fmt.Printf("fibMemo(%d) = %d\n", i, fibonacciMemo(i, memo))
    }
    
    // 4. 二分查找
    fmt.Println("\n二分查找:")
    arr := []int{1, 3, 5, 7, 9, 11, 13, 15, 17, 19}
    target := 7
    index := binarySearch(arr, target, 0, len(arr)-1)
    if index != -1 {
        fmt.Printf("在数组 %v 中找到 %d,索引为 %d\n", arr, target, index)
    } else {
        fmt.Printf("在数组 %v 中未找到 %d\n", arr, target)
    }
    
    // 5. 树形结构遍历
    fmt.Println("\n树形结构中序遍历:")
    root := &TreeNode{
        Value: 4,
        Left: &TreeNode{
            Value: 2,
            Left:  &TreeNode{Value: 1},
            Right: &TreeNode{Value: 3},
        },
        Right: &TreeNode{
            Value: 6,
            Left:  &TreeNode{Value: 5},
            Right: &TreeNode{Value: 7},
        },
    }
    root.inorderTraversal()
    fmt.Println()
    
    // 6. 汉诺塔问题
    fmt.Println("\n汉诺塔问题 (3个盘子):")
    hanoi(3, "A", "C", "B")
    
    // 7. 目录结构遍历
    fmt.Println("\n目录结构:")
    rootDir := &Directory{
        Name:  "root",
        Files: []string{"file1.txt", "file2.txt"},
        Directories: []*Directory{
            {
                Name:  "subdir1",
                Files: []string{"sub1.txt"},
                Directories: []*Directory{
                    {
                        Name:        "subsubdir1",
                        Files:       []string{"subsub1.txt"},
                        Directories: nil,
                    },
                },
            },
            {
                Name:        "subdir2",
                Files:       []string{"sub2.txt", "sub3.txt"},
                Directories: nil,
            },
        },
    }
    rootDir.printStructure("")
}

总结

  1. 函数定义

    • 使用func关键字
    • 支持多返回值
    • 支持命名返回值
    • 支持可变参数
  2. 函数特性

    • 函数是一等公民,可以作为值传递
    • 支持匿名函数
    • 支持闭包
    • 支持递归
  3. 高级特性

    • 高阶函数(接受或返回函数)
    • 闭包捕获外部变量
    • 函数类型定义
    • 函数作为结构体字段
  4. 最佳实践

    • 使用命名返回值提高可读性
    • 合理使用可变参数
    • 注意闭包中的变量捕获
    • 递归函数要有明确的终止条件
    • 使用函数类型提高代码复用性
updatedupdated2025-09-202025-09-20