练习
学完本章你应该掌握
- 能根据任务拆出无参函数、有参函数、单返回值函数和多返回值函数,而不是把所有逻辑都堆在
main里。 - 能正确使用普通参数、可变参数、
slice...展开传参和命名返回值,写出更灵活的函数接口。 - 能在函数中返回
bool、error等结果,并在调用方完成判断、分流和错误处理。 - 能在合适场景下使用匿名函数、高阶函数和闭包,把“行为”当作数据来传递和复用。
- 能理解普通值参数与指针参数的区别,并通过
&、*完成对外部变量的修改。 - 能把函数和前面学过的输入输出、基本类型、切片、map、判断、循环结合起来,写出结构更清晰的控制台程序。
简单
第 1 题:定义并调用问候函数
编写一个 Go 程序,完成下面要求:
- 定义一个无参无返回值函数
sayWelcome() - 这个函数输出
欢迎学习函数 - 在
main中调用它两次
查看参考答案
| |
输出结果:
| |
第 2 题:编写返回较大值的函数
编写一个函数 max(a, b int) int,完成下面要求:
- 接收两个整数
- 返回其中较大的那个值
- 在
main中调用max(18, 25),并输出max=25
查看参考答案
| |
第 3 题:编写返回布尔值的偶数判断函数
编写一个函数 isEven(n int) bool,完成下面要求:
- 如果
n是偶数,返回true - 否则返回
false - 在
main中分别测试8和11 - 输出格式如下:
| |
查看参考答案
| |
说明:这道题的重点是让函数返回一个 bool,再由调用方决定怎么输出结果。
第 4 题:用函数统计切片总和
已知有一个切片:
| |
请编写一个函数 sumSlice(nums []int) int,完成下面要求:
- 接收一个
[]int - 使用
for range计算总和 - 在
main中调用它,并输出total=24
查看参考答案
| |
第 5 题:修正可变参数的调用方式
下面程序想分别输出 6 和 15,但它现在不能通过编译。
请改正代码,让它正常运行:
| |
查看参考答案
修正后的代码如下:
| |
关键点:
- 向可变参数函数传切片时,要写成
base... - 数组不能直接展开,要先切成切片,再写成
arr[:]...
第 6 题:用命名返回值计算长方形信息
编写一个函数 rectStats(width, height int) (area int, perimeter int),完成下面要求:
- 使用命名返回值
- 返回长方形的面积和周长
- 在
main中调用rectStats(5, 3) - 输出:
| |
查看参考答案
| |
说明:命名返回值适合返回含义明确的多个结果,但函数体仍然要保持清晰,不要为了省几个字把逻辑写乱。
第 7 题:用指针参数给分数加分
编写一个函数 addBonus(score *int),完成下面要求:
- 接收一个整数指针
- 把这个分数加
10 - 在
main中定义score := 78 - 调用函数后输出修改后的结果
查看参考答案
| |
说明:如果函数参数写成 int,函数里改到的只是副本;这里传的是 &score,所以可以通过 *score 改到外部变量。
一般
第 8 题:实现带错误返回的安全除法
编写一个函数 safeDivide(a, b int) (int, error),完成下面要求:
- 如果
b == 0,返回错误除数不能为 0 - 否则返回
a / b - 在
main中分别测试safeDivide(20, 4)和safeDivide(20, 0) - 调用方拿到
error后先判断,再决定输出结果
查看参考答案
| |
输出结果:
| |
说明:返回 error 不是为了“让函数更复杂”,而是为了让调用方知道这次计算是否真的成功。
第 9 题:编写可变参数统计函数
编写一个函数 calcStats(nums ...int) (total int, avg float64),完成下面要求:
- 接收任意个整数
- 返回总和和平均值
- 如果一个数字都没传,平均值保持
0 - 在
main中准备切片scores := []int{80, 90, 85} - 使用
calcStats(scores...)调用它 - 输出:
| |
查看参考答案
| |
说明:这道题把可变参数、切片展开传参和命名返回值放到了一起,是函数章节里很典型的组合题。
第 10 题:编写成绩等级函数
编写一个函数 grade(score int) string,完成下面要求:
- 如果分数小于
0或大于100,返回非法 90 ~ 100返回A80 ~ 89返回B60 ~ 79返回C- 其他返回
D
然后在 main 中遍历下面这个切片,并逐行输出每个分数对应的等级:
| |
查看参考答案
| |
第 11 题:封装年龄查询函数
请把 map 查询逻辑封装成一个函数,完成下面要求:
- 先准备一张年龄表:
| |
- 编写函数
findAge(ages map[string]int, name string) (int, bool) - 再让用户输入一个姓名
- 调用这个函数
- 如果找到了,输出
小王 的年龄是 18 - 如果没找到,输出
没有找到该用户
查看参考答案
| |
说明:这道题的重点不是 map 本身,而是让你把“查询并返回结果”的逻辑收进函数里,让调用方只关心“找到了没有”。
第 12 题:使用立即执行匿名函数统计及格人数
已知有一个成绩切片:
| |
请使用“立即执行匿名函数”的写法,完成下面要求:
- 统计及格人数,及格线是
60 - 把结果保存到变量
passCount - 最后输出
passCount=4
查看参考答案
| |
说明:匿名函数不一定要先赋值给变量,也可以“定义完立刻执行”,这种写法常见于一次性的临时逻辑。
第 13 题:实现接收函数参数的计算器
编写一个高阶函数 calc(a, b int, op func(int, int) int) int,完成下面要求:
calc接收两个整数和一个函数参数- 这个函数参数负责决定“怎么计算”
- 在
main中用匿名函数分别完成两次调用: 第一次计算7 + 3第二次取7和3中的较大值 - 输出格式如下:
| |
查看参考答案
| |
说明:高阶函数的关键不在于“函数很多”,而在于“函数也能像普通值一样被传来传去”。
第 14 题:实现交换两个整数的函数
编写一个函数 swap(a, b *int),完成下面要求:
- 接收两个整数指针
- 交换它们指向的值
- 在
main中定义x := 3、y := 9 - 调用函数前后都输出一次
期望输出类似这样:
| |
查看参考答案
| |
说明:如果这里把函数参数写成 swap(a, b int),交换的只会是两个副本,main 里的 x 和 y 不会真的变化。
进阶
下面四题会把 01-06 单元里的输入、判断、循环、切片、map 与函数组合起来,更接近“先拆函数,再组织流程”的真实写法。
第 15 题:实现一个闭包计数器
编写一个函数 makeCounter(start int) func() int,完成下面要求:
- 外层函数接收起始值
start - 返回一个匿名函数
- 每次调用这个匿名函数时,都先把内部值加
1,再返回 - 在
main中这样测试:
| |
输出应为:
| |
查看参考答案
| |
说明:start 原本是外层函数里的变量,但返回的匿名函数把它“记住”了,所以多次调用时状态会持续保留下来。
第 16 题:用闭包生成筛选函数
编写一个函数 makeMinChecker(min int) func(int) bool,完成下面要求:
- 它返回一个新函数
- 这个新函数接收一个分数,并判断该分数是否大于等于
min - 再编写一个辅助函数
countByChecker(scores []int, checker func(int) bool) int - 使用下面这个切片做测试:
| |
- 创建两个检查函数:
passChecker := makeMinChecker(60)excellentChecker := makeMinChecker(90) - 分别统计及格人数和优秀人数
查看参考答案
| |
一种可能的输出结果:
| |
说明:这道题把“函数作为返回值”和“函数作为参数”都连起来了,能很好地体会函数复用的价值。
第 17 题:用函数表实现循环菜单
请编写一个程序,完成下面要求:
- 先准备成绩切片:
| |
- 编写三个普通函数:
calcTotal(scores []int) intcalcAvg(scores []int) float64bestScore(scores []int) int - 再准备一个函数表
map[int]func(),让它负责菜单分发:1输出总分2输出平均分3输出最高分 - 使用
for {}循环读取用户选项 - 输入
0时退出 - 输入其他不存在的编号时输出
无效选项
查看参考答案
| |
说明:这道题的重点不是菜单本身,而是体会“编号 -> 函数”的映射关系。分支一多,用函数表往往比堆很多层 if 更清晰。
第 18 题:拆分一个成绩录入分析器
请把下面这个需求拆成多个函数来实现:
- 编写
readScores() []int不断读取用户输入的成绩 输入-1时结束 如果分数小于0或大于100,输出分数无效,已跳过,然后继续下一轮 合法分数追加到切片里 - 编写
calcStats(scores []int) (int, float64, error)返回总分、平均分和错误信息 如果一个有效成绩都没有,返回错误没有有效成绩 - 编写
gradeByAvg(avg float64) stringavg >= 90返回Aavg >= 80返回Bavg >= 60返回C其他返回D - 在
main中调用这些函数,最后输出总分、平均分和平均分等级
查看参考答案
| |
说明:这道题把循环输入、切片追加、条件判断、错误返回和函数拆分全部串起来了。能顺利写出来,说明你已经开始真正把函数当成“组织程序结构”的工具在用了。