Go 语言循环语句
循环语句用于重复执行一段代码直到满足某个条件。Go 语言只有一种循环关键字 for,但它提供了多种形式来适应不同的循环需求。
🔄 for 循环的基本形式
经典三段式 for 循环
go
package main
import "fmt"
func main() {
// 基本的 for 循环:初始化; 条件; 后置语句
fmt.Println("数字 1 到 5:")
for i := 1; i <= 5; i++ {
fmt.Printf("%d ", i)
}
fmt.Println()
// 倒序循环
fmt.Println("倒数 5 到 1:")
for i := 5; i >= 1; i-- {
fmt.Printf("%d ", i)
}
fmt.Println()
// 步长不为 1 的循环
fmt.Println("偶数 2 到 10:")
for i := 2; i <= 10; i += 2 {
fmt.Printf("%d ", i)
}
fmt.Println()
// 嵌套循环 - 乘法表
fmt.Println("\n九九乘法表:")
for i := 1; i <= 9; i++ {
for j := 1; j <= i; j++ {
fmt.Printf("%d*%d=%d ", j, i, i*j)
}
fmt.Println()
}
}条件循环(类似 while)
go
func main() {
// 省略初始化和后置语句,只保留条件
count := 0
fmt.Println("条件循环:")
for count < 5 {
fmt.Printf("count = %d\n", count)
count++
}
// 无限循环(需要用 break 跳出)
fmt.Println("\n无限循环示例:")
counter := 0
for {
if counter >= 3 {
break // 跳出循环
}
fmt.Printf("无限循环第 %d 次\n", counter+1)
counter++
}
// 模拟 do-while 循环
fmt.Println("\n模拟 do-while:")
num := 10
for {
fmt.Printf("num = %d\n", num)
num--
if num < 8 {
break
}
}
}🎯 range 循环
遍历切片和数组
go
func main() {
// 遍历切片
fruits := []string{"苹果", "香蕉", "橙子", "葡萄"}
// 方式1:获取索引和值
fmt.Println("遍历水果(索引和值):")
for index, fruit := range fruits {
fmt.Printf("索引 %d: %s\n", index, fruit)
}
// 方式2:只获取索引
fmt.Println("\n只获取索引:")
for index := range fruits {
fmt.Printf("索引 %d\n", index)
}
// 方式3:只获取值
fmt.Println("\n只获取值:")
for _, fruit := range fruits {
fmt.Printf("水果: %s\n", fruit)
}
// 遍历数组
numbers := [5]int{10, 20, 30, 40, 50}
fmt.Println("\n遍历数组:")
for i, num := range numbers {
fmt.Printf("numbers[%d] = %d\n", i, num)
}
}遍历映射(map)
go
func main() {
// 遍历 map
studentGrades := map[string]int{
"Alice": 95,
"Bob": 87,
"Carol": 92,
"David": 78,
}
fmt.Println("学生成绩:")
for name, grade := range studentGrades {
fmt.Printf("%s: %d分\n", name, grade)
}
// 只获取键
fmt.Println("\n学生姓名:")
for name := range studentGrades {
fmt.Printf("学生: %s\n", name)
}
// 只获取值
fmt.Println("\n所有成绩:")
for _, grade := range studentGrades {
fmt.Printf("成绩: %d\n", grade)
}
// 注意:map 的遍历顺序是随机的
fmt.Println("\n多次遍历顺序可能不同:")
for i := 0; i < 3; i++ {
fmt.Printf("第%d次遍历: ", i+1)
for name := range studentGrades {
fmt.Printf("%s ", name)
}
fmt.Println()
}
}遍历字符串
go
import "unicode/utf8"
func main() {
// 遍历字符串(按字节)
str := "Hello, 世界!"
fmt.Println("按字节遍历:")
for i := 0; i < len(str); i++ {
fmt.Printf("字节 %d: %c (0x%02x)\n", i, str[i], str[i])
}
// 遍历字符串(按字符)
fmt.Println("\n按字符遍历:")
for index, char := range str {
fmt.Printf("位置 %d: %c (Unicode: %U)\n", index, char, char)
}
// 统计字符数
fmt.Printf("\n字符串长度: %d 字节\n", len(str))
fmt.Printf("字符数量: %d 个字符\n", utf8.RuneCountInString(str))
// 中文字符串示例
chinese := "你好世界"
fmt.Printf("\n中文字符串: %s\n", chinese)
fmt.Printf("字节长度: %d\n", len(chinese))
for i, char := range chinese {
fmt.Printf("位置 %d: %c\n", i, char)
}
}遍历通道(channel)
go
func main() {
// 创建并填充通道
ch := make(chan int, 5)
// 发送数据到通道
go func() {
for i := 1; i <= 5; i++ {
ch <- i * i // 发送平方数
}
close(ch) // 关闭通道
}()
// 遍历通道
fmt.Println("从通道接收数据:")
for value := range ch {
fmt.Printf("接收到: %d\n", value)
}
fmt.Println("通道已关闭,遍历结束")
}🛑 循环控制语句
break 语句
go
func main() {
// break 跳出当前循环
fmt.Println("使用 break 跳出循环:")
for i := 1; i <= 10; i++ {
if i == 6 {
break // 当 i 等于 6 时跳出循环
}
fmt.Printf("%d ", i)
}
fmt.Println("\n循环结束")
// 在嵌套循环中使用 break
fmt.Println("\n嵌套循环中的 break:")
for i := 1; i <= 3; i++ {
fmt.Printf("外层循环 i = %d\n", i)
for j := 1; j <= 3; j++ {
if j == 2 {
break // 只跳出内层循环
}
fmt.Printf(" 内层循环 j = %d\n", j)
}
}
// 查找数组中的元素
numbers := []int{1, 3, 5, 7, 9, 2, 4, 6, 8}
target := 7
fmt.Printf("\n在数组中查找 %d:\n", target)
for i, num := range numbers {
if num == target {
fmt.Printf("找到 %d 在索引 %d 位置\n", target, i)
break
}
fmt.Printf("检查索引 %d: %d\n", i, num)
}
}continue 语句
go
func main() {
// continue 跳过当前迭代,继续下一次迭代
fmt.Println("打印奇数 (1-10):")
for i := 1; i <= 10; i++ {
if i%2 == 0 {
continue // 跳过偶数
}
fmt.Printf("%d ", i)
}
fmt.Println()
// 处理数组时跳过特定值
scores := []int{85, -1, 92, 88, -1, 76, 94}
validScores := 0
totalScore := 0
fmt.Println("\n处理成绩(跳过无效成绩 -1):")
for i, score := range scores {
if score == -1 {
fmt.Printf("索引 %d: 跳过无效成绩\n", i)
continue
}
fmt.Printf("索引 %d: 有效成绩 %d\n", i, score)
validScores++
totalScore += score
}
if validScores > 0 {
average := float64(totalScore) / float64(validScores)
fmt.Printf("平均成绩: %.2f\n", average)
}
}标签和 goto
go
func main() {
// 使用标签控制嵌套循环
fmt.Println("使用标签的嵌套循环:")
OuterLoop: // 标签
for i := 1; i <= 3; i++ {
for j := 1; j <= 3; j++ {
if i == 2 && j == 2 {
fmt.Printf("在 i=%d, j=%d 时跳出所有循环\n", i, j)
break OuterLoop // 跳出到标签位置
}
fmt.Printf("i=%d, j=%d\n", i, j)
}
}
fmt.Println("嵌套循环结束")
// continue 配合标签
fmt.Println("\n使用标签的 continue:")
ContinueOuter:
for i := 1; i <= 3; i++ {
for j := 1; j <= 3; j++ {
if j == 2 {
fmt.Printf("在 i=%d, j=%d 时跳过外层循环的剩余内层循环\n", i, j)
continue ContinueOuter
}
fmt.Printf("i=%d, j=%d\n", i, j)
}
fmt.Printf("外层循环 i=%d 的内层循环完成\n", i)
}
}🎯 实际应用示例
数据处理和统计
go
import (
"fmt"
"math"
"sort"
)
func main() {
// 学生成绩数据
students := map[string][]int{
"Alice": {85, 92, 78, 88, 90},
"Bob": {76, 81, 69, 85, 79},
"Carol": {95, 89, 92, 96, 93},
"David": {72, 68, 75, 71, 77},
}
// 处理每个学生的成绩
for name, scores := range students {
fmt.Printf("\n学生: %s\n", name)
fmt.Printf("原始成绩: %v\n", scores)
// 计算总分和平均分
total := 0
for _, score := range scores {
total += score
}
average := float64(total) / float64(len(scores))
// 找最高分和最低分
maxScore := scores[0]
minScore := scores[0]
for _, score := range scores {
if score > maxScore {
maxScore = score
}
if score < minScore {
minScore = score
}
}
// 计算方差
variance := 0.0
for _, score := range scores {
diff := float64(score) - average
variance += diff * diff
}
variance /= float64(len(scores))
standardDev := math.Sqrt(variance)
// 计算等级
grade := calculateGrade(average)
fmt.Printf("总分: %d\n", total)
fmt.Printf("平均分: %.2f\n", average)
fmt.Printf("最高分: %d\n", maxScore)
fmt.Printf("最低分: %d\n", minScore)
fmt.Printf("标准差: %.2f\n", standardDev)
fmt.Printf("等级: %s\n", grade)
}
// 班级整体统计
fmt.Println("\n=== 班级整体统计 ===")
allScores := []float64{}
for _, scores := range students {
total := 0
for _, score := range scores {
total += score
}
average := float64(total) / float64(len(scores))
allScores = append(allScores, average)
}
// 排序平均分
sort.Float64s(allScores)
fmt.Printf("平均分排序: %.2f\n", allScores)
classTotal := 0.0
for _, avg := range allScores {
classTotal += avg
}
classAverage := classTotal / float64(len(allScores))
fmt.Printf("班级平均分: %.2f\n", classAverage)
}
func calculateGrade(average float64) string {
switch {
case average >= 90:
return "A"
case average >= 80:
return "B"
case average >= 70:
return "C"
case average >= 60:
return "D"
default:
return "F"
}
}素数生成器
go
import "math"
func main() {
// 生成前20个素数
fmt.Println("前20个素数:")
primes := generatePrimes(20)
for i, prime := range primes {
fmt.Printf("第%d个素数: %d\n", i+1, prime)
}
// 找100以内的所有素数
fmt.Println("\n100以内的素数:")
primesUnder100 := sieveOfEratosthenes(100)
for i, prime := range primesUnder100 {
if i > 0 && i%10 == 0 {
fmt.Println()
}
fmt.Printf("%3d ", prime)
}
fmt.Println()
}
// 生成前 n 个素数
func generatePrimes(n int) []int {
primes := []int{}
num := 2
for len(primes) < n {
if isPrime(num) {
primes = append(primes, num)
}
num++
}
return primes
}
// 判断是否为素数
func isPrime(n int) bool {
if n < 2 {
return false
}
if n == 2 {
return true
}
if n%2 == 0 {
return false
}
// 只需检查到 sqrt(n)
sqrtN := int(math.Sqrt(float64(n)))
for i := 3; i <= sqrtN; i += 2 {
if n%i == 0 {
return false
}
}
return true
}
// 埃拉托斯特尼筛法
func sieveOfEratosthenes(max int) []int {
// 创建布尔数组
isPrime := make([]bool, max+1)
for i := range isPrime {
isPrime[i] = true
}
isPrime[0] = false
isPrime[1] = false
// 筛法
for i := 2; i*i <= max; i++ {
if isPrime[i] {
// 标记 i 的倍数为非素数
for j := i * i; j <= max; j += i {
isPrime[j] = false
}
}
}
// 收集素数
primes := []int{}
for i := 2; i <= max; i++ {
if isPrime[i] {
primes = append(primes, i)
}
}
return primes
}文本处理和分析
go
import (
"fmt"
"strings"
"unicode"
)
func main() {
text := `Go语言是Google开发的开源编程语言。
它具有简洁的语法、高效的性能和强大的并发能力。
Go适用于云原生应用、微服务、Web开发等多个领域。
学习Go语言,你可以构建现代化的软件系统。`
fmt.Println("原文本:")
fmt.Println(text)
fmt.Println()
// 文本统计
analyzer := NewTextAnalyzer(text)
analyzer.Analyze()
analyzer.PrintStatistics()
}
type TextAnalyzer struct {
text string
lines []string
words []string
characters int
letters int
digits int
spaces int
punctuation int
wordCount map[string]int
}
func NewTextAnalyzer(text string) *TextAnalyzer {
return &TextAnalyzer{
text: text,
wordCount: make(map[string]int),
}
}
func (ta *TextAnalyzer) Analyze() {
// 按行分割
ta.lines = strings.Split(ta.text, "\n")
// 字符统计
for _, char := range ta.text {
ta.characters++
switch {
case unicode.IsLetter(char):
ta.letters++
case unicode.IsDigit(char):
ta.digits++
case unicode.IsSpace(char):
ta.spaces++
case unicode.IsPunct(char):
ta.punctuation++
}
}
// 单词统计
for _, line := range ta.lines {
words := strings.Fields(line)
for _, word := range words {
// 清理标点符号
cleanWord := ""
for _, char := range word {
if unicode.IsLetter(char) || unicode.IsDigit(char) {
cleanWord += string(char)
}
}
if cleanWord != "" {
cleanWord = strings.ToLower(cleanWord)
ta.words = append(ta.words, cleanWord)
ta.wordCount[cleanWord]++
}
}
}
}
func (ta *TextAnalyzer) PrintStatistics() {
fmt.Println("=== 文本分析结果 ===")
fmt.Printf("行数: %d\n", len(ta.lines))
fmt.Printf("总字符数: %d\n", ta.characters)
fmt.Printf("字母数: %d\n", ta.letters)
fmt.Printf("数字数: %d\n", ta.digits)
fmt.Printf("空格数: %d\n", ta.spaces)
fmt.Printf("标点符号数: %d\n", ta.punctuation)
fmt.Printf("单词总数: %d\n", len(ta.words))
fmt.Printf("不重复单词数: %d\n", len(ta.wordCount))
// 词频统计(显示前10个)
fmt.Println("\n词频统计 (前10个):")
type wordFreq struct {
word string
count int
}
var frequencies []wordFreq
for word, count := range ta.wordCount {
frequencies = append(frequencies, wordFreq{word, count})
}
// 按频率排序
for i := 0; i < len(frequencies)-1; i++ {
for j := i + 1; j < len(frequencies); j++ {
if frequencies[i].count < frequencies[j].count {
frequencies[i], frequencies[j] = frequencies[j], frequencies[i]
}
}
}
// 显示前10个
maxDisplay := 10
if len(frequencies) < maxDisplay {
maxDisplay = len(frequencies)
}
for i := 0; i < maxDisplay; i++ {
fmt.Printf("%d. %s: %d次\n", i+1, frequencies[i].word, frequencies[i].count)
}
}💡 性能优化技巧
循环优化
go
import (
"fmt"
"time"
)
func main() {
// 测试数据
size := 1000000
data := make([]int, size)
for i := range data {
data[i] = i
}
// 方法1:普通循环
start := time.Now()
sum1 := 0
for i := 0; i < len(data); i++ {
sum1 += data[i]
}
duration1 := time.Since(start)
// 方法2:range 循环
start = time.Now()
sum2 := 0
for _, value := range data {
sum2 += value
}
duration2 := time.Since(start)
// 方法3:预先计算长度
start = time.Now()
sum3 := 0
length := len(data)
for i := 0; i < length; i++ {
sum3 += data[i]
}
duration3 := time.Since(start)
fmt.Printf("普通循环: 结果=%d, 耗时=%v\n", sum1, duration1)
fmt.Printf("range循环: 结果=%d, 耗时=%v\n", sum2, duration2)
fmt.Printf("预计算长度: 结果=%d, 耗时=%v\n", sum3, duration3)
// 避免在循环中进行重复计算
fmt.Println("\n避免重复计算示例:")
// ❌ 不好的做法
start = time.Now()
count1 := 0
for i := 0; i < 10000; i++ {
for j := 0; j < len(data)/1000; j++ { // 每次都计算 len(data)
count1++
}
}
badDuration := time.Since(start)
// ✅ 好的做法
start = time.Now()
count2 := 0
innerLen := len(data) / 1000 // 预先计算
for i := 0; i < 10000; i++ {
for j := 0; j < innerLen; j++ {
count2++
}
}
goodDuration := time.Since(start)
fmt.Printf("重复计算: 次数=%d, 耗时=%v\n", count1, badDuration)
fmt.Printf("预先计算: 次数=%d, 耗时=%v\n", count2, goodDuration)
fmt.Printf("性能提升: %.2fx\n", float64(badDuration)/float64(goodDuration))
}🎓 小结
本章我们全面学习了 Go 语言的循环语句:
- ✅ for 循环:三段式循环、条件循环、无限循环
- ✅ range 循环:遍历切片、数组、映射、字符串、通道
- ✅ 循环控制:break、continue、标签控制
- ✅ 实际应用:数据统计、素数生成、文本分析
- ✅ 性能优化:循环优化技巧和最佳实践
Go 语言的 for 循环功能强大且灵活,配合 range 关键字可以优雅地处理各种数据结构的遍历。
接下来,我们将学习 Go 语言函数,了解如何组织和重用代码。
循环使用建议
- 优先使用 range 循环遍历数据结构
- 避免在循环中进行重复的复杂计算
- 合理使用 break 和 continue 控制循环流程
- 注意嵌套循环的性能影响