zhuts aba9ec24e3 feat: 新增第七课函数例程与配套测试说明 3 дней назад
..
README.md aba9ec24e3 feat: 新增第七课函数例程与配套测试说明 3 дней назад
main.go aba9ec24e3 feat: 新增第七课函数例程与配套测试说明 3 дней назад
main_test.go aba9ec24e3 feat: 新增第七课函数例程与配套测试说明 3 дней назад

README.md

第 07 课:函数

学习目标

第一课已经见过函数,这一课正式学习怎样拆分逻辑:参数传入数据、return 返回结果、多返回值表达是否有效,以及可变参数。

先手敲 main.go,运行成功后再阅读配套的 main_test.go。不要一开始就同时抄完测试代码。本课共享根目录的 go.mod,无需第三方依赖。

1. 声明和调用

func add(a, b int) int {
    return a + b
}

result := add(2, 3) // 这一行调用放在 main 等函数内部。
  • func:声明函数。
  • add:函数名。
  • a, b int:两个 int 参数,完整写法是 a int, b int。
  • 参数列表后面的 int:返回值类型。
  • return:结束当前函数,并把结果交给调用方;不是结束整个程序。

与 C 相比,Go 的类型写在名称后面,而且支持直接返回多个值。不需要为后面定义的普通函数先写函数原型,也不能直接在另一个函数内部声明具名函数;后续会学匿名函数。

函数定义的前后顺序不决定调用顺序:程序完成初始化后进入 main,按实际调用执行。普通函数不会因为写在文件里就自动运行。

2. 参数与值传递

func increase(value int) int {
    value++
    return value
}

调用 increase(count) 时,参数接收的是值的副本;修改内部整数 value,不会改变调用方的 count。想保留新值,可以用 count = increase(count)。

Go 的参数都是按值传递。但切片和 map 的值包含对底层数据的引用,复制参数值不等于复制全部数据:函数内修改切片元素或 map 条目,可能影响调用方。不能理解为“传进函数的任何数据都完全独立”。指针和更深入的共享行为后续单独学习。

3. 多返回值与提前返回

func average(scores []int) (float64, bool) {
    if len(scores) == 0 {
        return 0, false
    }
    // 累加计算……
    return 85, true // 此处仅示意返回形式,完整计算见 main.go。
}

调用时按顺序接收:

avg, ok := average(scores)

本课约定:ok 为 true 才表示平均值有效。空切片提前返回 false;真正的零分则返回 (0, true),避免混淆。

不需要某个返回值,可以使用 _,例如 _, ok = average(nil)。这里使用 =,因为 ok 已在同一作用域声明。

该函数只检查是否为空,不验证成绩是否位于 0~100,也暂不处理极大整数累加溢出。后续可在学习 error 后扩展输入校验。

4. 可变参数

func sum(values ...int) int {
    total := 0
    for _, value := range values {
        total += value
    }
    return total
}
  • 调用 sum(1, 2, 3) 可以传多个整数,sum() 也合法。
  • 在函数内部,values 作为 []int 使用。
  • 已有切片时写 sum(numbers...),将切片展开为参数。
  • 如果有其他参数,可变参数必须放在最后。

先掌握常规函数即可,本课暂不引入递归、闭包、泛型和 defer。

编译并运行

在仓库根目录执行:

New-Item -ItemType Directory -Force bin/07_functions | Out-Null
go build -o ./bin/07_functions/functions.exe ./lessons/07_functions
.\bin\07_functions\functions.exe

修改源码后需要重新编译。快速编译并运行:

go run ./lessons/07_functions

或者从根目录进入本课:

Set-Location lessons/07_functions
go run .

预期输出

=== 无参数函数 ===
欢迎学习 Go 函数

=== 参数与返回值 ===
2 + 3 = 5

=== 值传递 ===
原变量:10,函数返回的新值:11

=== 多返回值与提前返回 ===
平均分:85.00
没有成绩,无法计算平均分

=== 可变参数 ===
直接传入多个整数:6
展开切片作为参数:60
不传参数:0

测试

在仓库根目录执行:

go test -v ./lessons/07_functions

测试覆盖加法、整数值传递、正常平均值、小数平均值、零分、空切片和可变参数。这里的小数用例是可以精确表示的 80.5,因此直接比较;一般浮点计算测试可能需要容差判断。

动手练习

  • 把 add 的输入改成负数,观察结果。
  • 用 count = increase(count) 更新调用方变量,比较前后区别。
  • 修改成绩切片,核对平均分;再改为空切片,观察提前返回。
  • 新写 max(a, b int) int,返回较大的值。
  • 为 max 添加相等、正数、负数的测试用例。
  • 使用 sum 计算一组新整数的总和。

若另行手敲,放到本课的 practice/ 子目录,用 go run ./lessons/07_functions/practice 运行,不要在同一个包中重复声明 main 或其他同名函数。

下一课建议学习结构体,把姓名、年龄、成绩等不同类型的数据组合成一个对象。

上一课:map 键值对 · 学习总览