章节

5.7 练习

本篇通过 13 道分级练习巩固 for 的多种写法、遍历与流程控制,并能独立完成基础循环统计、查找与交互程序。

练习

学完本章你应该掌握

  • 能根据场景选择传统 forwhile 模式、do-while 模式和 for range
  • 能使用循环完成计数、累加、累乘、筛选、查找等基础任务,并写对条件边界。
  • 能遍历切片与 map,正确处理索引、键值以及 map 遍历顺序不固定的特点。
  • 能使用 breakcontinue 改变循环流程,并识别由更新语句遗漏带来的死循环问题。
  • 能在循环中结合输入、判断、切片、map 写出更完整的控制台小程序。
  • 能把 for 的知识迁移到数据统计、菜单交互、重复录入、倒计时等常见场景。

简单

第 1 题:打印 1 到 5 并求和

第 1 题 简单

编写一个 Go 程序,完成下面要求:

  • 使用传统 for 循环
  • 依次输出 15
  • 再输出它们的总和

示例输出:

1
2
3
4
5
6
1
2
3
4
5
sum=15
查看参考答案
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
package main

import "fmt"

func main() {
	sum := 0

	for i := 1; i <= 5; i++ {
		fmt.Println(i)
		sum += i
	}

	fmt.Printf("sum=%d\n", sum)
}

说明:这道题的重点是把“循环次数已知”的场景写成熟悉的 for 初始化; 条件; 后置操作 结构。

第 2 题:补全倒序偶数循环

第 2 题 简单

补全下面代码中的空白,让程序输出:

1
2
3
4
5
10
8
6
4
2
1
2
3
4
5
6
7
8
9
package main

import "fmt"

func main() {
	for i := ____; i >= ____; i ____ {
		fmt.Println(i)
	}
}
查看参考答案

补全后的代码如下:

1
2
3
4
5
6
7
8
9
package main

import "fmt"

func main() {
	for i := 10; i >= 2; i -= 2 {
		fmt.Println(i)
	}
}

说明:这道题练的是“倒序循环”和“步长不一定是 1”。后置操作除了 i++,也可以写成 i--i += 2i -= 2

第 3 题:用 while 模式计算阶乘

第 3 题 简单

编写一个程序:

  • 读取一个正整数 n
  • 使用 while 模式,也就是 for 条件 {} 的写法
  • 计算 n!
  • 输出结果

例如输入:

1
5

输出:

1
120
查看参考答案
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
package main

import "fmt"

func main() {
	var n int

	fmt.Print("请输入一个正整数:")
	fmt.Scan(&n)

	result := 1
	for n > 0 {
		result *= n
		n--
	}

	fmt.Println(result)
}

说明:for n > 0 {} 就是 Go 里的 while 模式。循环变量的更新要写在循环体里,否则很容易变成死循环。

第 4 题:用 do-while 模式打印倒计时

第 4 题 简单

请使用 for {} + break 模拟 do-while 模式,完成下面任务:

  • 定义 count := 3
  • 每轮先输出 count
  • 再让 count--
  • count == 0 时结束循环

输出结果应为:

1
2
3
3
2
1
查看参考答案
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
package main

import "fmt"

func main() {
	count := 3

	for {
		fmt.Println(count)
		count--

		if count == 0 {
			break
		}
	}
}

说明:这道题的关键不是“打印倒计时”,而是体会 do-while 模式的顺序是“先执行一次,再判断要不要退出”。

第 5 题:修正 continue 造成的死循环

第 5 题 简单

下面程序的目标是输出:

1
2
3
4
1
2
4
5

但它现在会卡住。请改正后让它正常结束。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
package main

import "fmt"

func main() {
	i := 1

	for i <= 5 {
		if i == 3 {
			continue
		}

		fmt.Println(i)
		i++
	}
}
查看参考答案

修正后的代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
package main

import "fmt"

func main() {
	i := 1

	for i <= 5 {
		if i == 3 {
			i++
			continue
		}

		fmt.Println(i)
		i++
	}
}

原因说明:

  • i == 3 时,程序会直接执行 continue
  • 原代码里的 i++continue 后面,所以这一轮不会执行
  • i 一直停在 3,循环条件始终成立,于是程序陷入死循环

一般

第 6 题:遍历切片输出编号和名称

第 6 题 一般

已知下面这个切片:

1
langs := []string{"Go", "切片", "循环"}

请使用 for range 输出:

1
2
3
第1个:Go
第2个:切片
第3个:循环
查看参考答案
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
package main

import "fmt"

func main() {
	langs := []string{"Go", "切片", "循环"}

	for index, lang := range langs {
		fmt.Printf("第%d个:%s\n", index+1, lang)
	}
}

说明:遍历切片时,range 返回的是索引和值。如果想把编号显示成“第 1 个”,记得把索引加 1

第 7 题:统计 1 到 n 中 3 的倍数

第 7 题 一般

编写一个程序,完成下面要求:

  • 读取一个整数 n
  • 如果 n <= 0,输出 n 必须大于 0
  • 否则统计 1 ~ n 之间能被 3 整除的数字个数和总和
  • 最后输出 count=...total=...

例如输入:

1
10

输出:

1
2
count=3
total=18
查看参考答案
 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
package main

import "fmt"

func main() {
	var n int

	fmt.Print("请输入 n:")
	fmt.Scan(&n)

	if n <= 0 {
		fmt.Println("n 必须大于 0")
		return
	}

	count := 0
	total := 0

	for i := 1; i <= n; i++ {
		if i%3 == 0 {
			count++
			total += i
		}
	}

	fmt.Printf("count=%d\n", count)
	fmt.Printf("total=%d\n", total)
}

说明:这道题把循环和条件判断放到了一起,是最常见的“边遍历、边筛选、边统计”写法。

第 8 题:统计成绩切片的总分、平均分和及格人数

第 8 题 一般

已知下面这个成绩切片:

1
scores := []int{78, 92, 56, 84, 67}

请编写程序,完成下面要求:

  • 使用 for range 遍历切片
  • 计算总分 total
  • 计算平均分 avg,保留 1 位小数
  • 统计及格人数 passCount,及格线是 60

示例输出:

1
2
3
total=377
avg=75.4
passCount=4
查看参考答案
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package main

import "fmt"

func main() {
	scores := []int{78, 92, 56, 84, 67}

	total := 0
	passCount := 0

	for _, score := range scores {
		total += score
		if score >= 60 {
			passCount++
		}
	}

	avg := float64(total) / float64(len(scores))

	fmt.Printf("total=%d\n", total)
	fmt.Printf("avg=%.1f\n", avg)
	fmt.Printf("passCount=%d\n", passCount)
}

说明:这道题虽然主角是 for range,但想把平均分算对,仍然需要用到前面学过的类型转换。

第 9 题:遍历 map 输出高价商品

第 9 题 一般

已知下面这个商品价格表:

1
2
3
4
5
6
prices := map[string]float64{
	"苹果":  5.5,
	"牛奶":  12.0,
	"洗发水": 39.9,
	"书包":  128.0,
}

请编写程序,完成下面要求:

  • 使用 for range 遍历这个 map
  • 只输出价格大于等于 30 的商品
  • 同时统计这类商品的数量 count
  • 再统计它们的总价 total

一种可能的输出结果:

1
2
3
4
洗发水: 39.9
书包: 128.0
count=2
total=167.9
查看参考答案
 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
package main

import "fmt"

func main() {
	prices := map[string]float64{
		"苹果":  5.5,
		"牛奶":  12.0,
		"洗发水": 39.9,
		"书包":  128.0,
	}

	count := 0
	total := 0.0

	for name, price := range prices {
		if price < 30 {
			continue
		}

		fmt.Printf("%s: %.1f\n", name, price)
		count++
		total += price
	}

	fmt.Printf("count=%d\n", count)
	fmt.Printf("total=%.1f\n", total)
}

说明:前面几行商品输出的顺序不固定,因为 map 的遍历顺序本来就不保证一致。只要统计结果正确即可。

第 10 题:用 break 找到第一个及格分数

第 10 题 一般

已知下面这个切片:

1
scores := []int{45, 58, 61, 73, 90}

请编写程序,完成下面要求:

  • 遍历切片
  • 找到第一个大于等于 60 的分数
  • 输出它的下标和分数
  • 找到后立即结束循环
  • 如果整个切片里都没有及格分数,输出 未找到及格分数

示例输出:

1
2
index=2
score=61
查看参考答案
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import "fmt"

func main() {
	scores := []int{45, 58, 61, 73, 90}
	found := false

	for index, score := range scores {
		if score >= 60 {
			fmt.Printf("index=%d\n", index)
			fmt.Printf("score=%d\n", score)
			found = true
			break
		}
	}

	if !found {
		fmt.Println("未找到及格分数")
	}
}

说明:break 很适合“找到就停”的场景。它能避免无意义地继续遍历后面的元素。

进阶

下面三题会把 01-05 单元里的输入、判断、切片、map 和 for 一起用起来,更接近真实的控制台程序。

第 11 题:编写一个循环菜单

第 11 题 进阶

请编写一个程序,完成下面要求:

  • 先准备一个成绩切片:
1
scores := []int{78, 92, 85, 66}
  • 使用 for {} 做一个循环菜单
  • 每轮提示用户输入一个选项: 1 表示输出总分 2 表示输出及格人数 0 表示退出程序
  • 其他输入输出 无效选项
  • 菜单要能重复使用,直到用户输入 0
  • 选项分流要求使用 switch
查看参考答案
 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
package main

import "fmt"

func main() {
	scores := []int{78, 92, 85, 66}

	for {
		var choice int

		fmt.Print("请输入选项(1总分 2及格人数 0退出):")
		fmt.Scan(&choice)

		switch choice {
		case 1:
			total := 0
			for _, score := range scores {
				total += score
			}
			fmt.Printf("总分:%d\n", total)
		case 2:
			passCount := 0
			for _, score := range scores {
				if score >= 60 {
					passCount++
				}
			}
			fmt.Printf("及格人数:%d\n", passCount)
		case 0:
			fmt.Println("退出程序")
			return
		default:
			fmt.Println("无效选项")
			continue
		}
	}
}

说明:这道题会把死循环、switch、切片遍历和统计逻辑连在一起,是一个很典型的“控制台菜单”场景。

第 12 题:使用死循环做 5 秒倒计时

第 12 题 进阶

请编写一个程序,完成下面要求:

  • 使用 for {} 创建死循环
  • 5 开始倒计时
  • 每秒输出一个数字
  • 输出顺序是 54321
  • 倒计时结束后输出 开始

要求:

  • 使用 time.Sleep(1 * time.Second) 控制每轮间隔
  • 倒计时结束时要主动跳出循环
查看参考答案
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main

import (
	"fmt"
	"time"
)

func main() {
	seconds := 5

	for {
		fmt.Println(seconds)
		time.Sleep(1 * time.Second)

		seconds--
		if seconds == 0 {
			break
		}
	}

	fmt.Println("开始")
}

说明:for {} 会一直循环,所以必须自己设计退出条件。time.Sleep 用来让程序暂停 1 秒,避免一瞬间把所有数字都打印完。

第 13 题:录入成绩直到输入 -1

第 13 题 进阶

请编写一个程序,完成下面要求:

  • 不断读取用户输入的成绩
  • 如果输入 -1,结束录入
  • 如果分数小于 0 或大于 100,输出 分数无效,已跳过,并继续下一轮
  • 对有效成绩统计人数 count、总分 total
  • 最后输出平均分 avg,保留 1 位小数
  • 如果用户没有输入任何有效成绩,输出 没有有效成绩

示例交互可以类似这样:

1
2
3
4
5
6
7
8
请输入成绩(-1 结束):80
请输入成绩(-1 结束):150
分数无效,已跳过
请输入成绩(-1 结束):90
请输入成绩(-1 结束):-1
count=2
total=170
avg=85.0
查看参考答案
 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
package main

import "fmt"

func main() {
	count := 0
	total := 0

	for {
		var score int

		fmt.Print("请输入成绩(-1 结束):")
		fmt.Scan(&score)

		if score == -1 {
			break
		}

		if score < 0 || score > 100 {
			fmt.Println("分数无效,已跳过")
			continue
		}

		count++
		total += score
	}

	if count == 0 {
		fmt.Println("没有有效成绩")
		return
	}

	avg := float64(total) / float64(count)

	fmt.Printf("count=%d\n", count)
	fmt.Printf("total=%d\n", total)
	fmt.Printf("avg=%.1f\n", avg)
}

说明:这道题是本章很有代表性的综合题。for {} 负责反复读取,break 负责结束录入,continue 负责跳过非法数据,最后再做一次统计输出。

本文禁止转载
使用 Hugo 构建
主题 StackJimmy 设计 由 Hobin 魔改
最近构建时间:2026-04-17 19:07:48 CST
载入天数...载入时分秒...
发表了 1 篇文章 · 发表了 152 篇笔记 · 总计 18 万 0 千字