文章目录
- 零、概述
- 一、for循环基础
- 1. 完整格式(三部分控制)
- 2. 省略格式(简化写法)
- 二、无限循环
- 三、for range遍历
- 四、嵌套循环
- 五、循环控制语句
- 1. break:退出循环
- 2. continue:跳过本次迭代
- 3. goto:无条件跳转(谨慎使用)
零、概述
场景 | 推荐写法 | 示例代码 |
---|---|---|
固定次数循环 | 完整格式 for i:=0; i<n; i++ | for i:=0; i<10; i++ { ... } |
条件循环(类似while) | 省略格式 for condition { ... } | for x<100 { x *= 2; } |
遍历集合 | for range | for idx, val := range slice { ... } |
多层循环中断 | break label | outer: for { if cond { break outer; } } |
跳过当前迭代 | continue | if val%2==0 { continue; } |
注意:
- 循环变量作用域:
- 完整格式中,
i := 0
声明的变量作用域仅限循环体内。 - 提前声明的循环变量(如
var i int
)作用域为外层块。
- 完整格式中,
- for range的坑:
- 遍历切片时,
value
是元素副本,修改value
不影响原切片,需通过索引修改。 - 遍历Map时,每次迭代顺序不确定(底层哈希表特性)。
- 遍历切片时,
- 性能优化:
- 避免在循环中执行高耗时操作(如网络请求、文件IO)。
- 大切片遍历时,可使用
for i := 0; i < len(slice); i++
替代for range
,避免复制值。
一、for循环基础
1. 完整格式(三部分控制)
for [初始化语句]; [条件表达式]; [后置语句] {// 循环体
}
- 初始化语句:设置循环变量初始值(如
i := 0
),仅执行一次。 - 条件表达式:决定循环是否继续(如
i < 10
),每次循环前判断。 - 后置语句:更新循环变量(如
i++
),每次循环后执行。
示例:计算1-100之和
sum := 0
for i := 1; i <= 100; i++ {sum += i
}
fmt.Println("总和:", sum) // 输出:5050
2. 省略格式(简化写法)
(1)省略初始化语句
var i int = 1 // 提前声明循环变量
for ; i <= 10; i++ { // 省略初始化部分fmt.Print(i, " ")
}
(2)省略后置语句
for i := 1; i <= 10; { // 省略 i++,在循环体内更新fmt.Print(i, " ")i++
}
(3)完全省略(类似while循环)
sum := 1
for sum < 100 { // 仅保留条件表达式,等价于 while(sum < 100)sum *= 2 // 循环体内更新变量
}
fmt.Println("最终值:", sum) // 输出:128
二、无限循环
省略条件表达式即可实现无限循环,需通过break
、return
等语句退出。
语法形式
for { // 无限循环// 循环体if condition {break // 满足条件时退出}
}
示例:模拟重试机制
attempts := 0
for {if attempts >= 3 {fmt.Println("重试失败")break}fmt.Println("尝试第", attempts+1, "次")if success := tryOperation(); success { // 假设 tryOperation 返回是否成功fmt.Println("操作成功")break}attempts++
}
三、for range遍历
for range
是Go语言特有的遍历方式,可迭代数组、切片、Map、字符串、通道(Channel) 等数据结构。
语法格式
for [index, value] := range iterable {// 循环体
}
- 数组/切片:
index
为索引,value
为元素值(副本)。 - Map:
index
为键(Key),value
为值(Value)。 - 字符串:
index
为字节偏移量,value
为 Unicode 码点(rune类型)。
示例:遍历切片和Map
(1)遍历切片
nums := []int{1, 3, 5, 7}
for idx, num := range nums {nums[idx] = num * 2 // 通过索引修改原切片fmt.Printf("索引 %d,值 %d\n", idx, num)
}
fmt.Println("修改后的切片:", nums) // 输出:[2 6 10 14]
(2)遍历Map
user := map[string]int{"Alice": 25, "Bob": 30}
for name, age := range user {fmt.Printf("%s 的年龄是 %d\n", name, age)
}
// 输出顺序不固定,可能为:
// Alice 的年龄是 25
// Bob 的年龄是 30
(3)遍历字符串(Unicode支持)
str := "Go语言"
for idx, r := range str { // r 为 rune 类型,代表 Unicode 字符fmt.Printf("字符 %c 位于字节位置 %d\n", r, idx)
}
// 输出:
// 字符 G 位于字节位置 0
// 字符 o 位于字节位置 1
// 字符 语 位于字节位置 2(UTF-8编码占3字节)
// 字符 言 位于字节位置 5(UTF-8编码占3字节)
四、嵌套循环
在循环体内包含另一个循环,适用于需要多层迭代的场景(如矩阵运算、生成表格等)。
示例1:打印九九乘法表
for i := 1; i <= 9; i++ {for j := 1; j <= i; j++ {fmt.Printf("%d×%d=%-3d", j, i, i*j) // %-3d 左对齐,宽度3}fmt.Println() // 每行结束换行
}
示例2:查找素数(埃拉托斯特尼筛法)
max := 100
isPrime := make([]bool, max+1)
//make
//用于创建并初始化引用类型(切片、map、通道)。
//它会为这些类型分配内存空间,并返回一个初始化后的类型实例(非 nil)。
for i := 2; i <= max; i++ {isPrime[i] = true // 初始化为素数
}
for i := 2; i*i <= max; i++ { // 只检查到平方根if isPrime[i] {for j := i * i; j <= max; j += i { // 标记非素数isPrime[j] = false}}
}
// 输出结果
fmt.Print("素数列表:")
for i := 2; i <= max; i++ {if isPrime[i] {fmt.Print(i, " ")}
}
五、循环控制语句
1. break:退出循环
- 作用:终止当前循环,跳出循环体。
- 标签用法:在嵌套循环中,
break [标签]
可退出指定标签的外层循环。
示例:带标签的break
outer:
for i := 0; i < 3; i++ {for j := 0; j < 3; j++ {if i == 1 && j == 1 {break outer // 退出外层循环}fmt.Printf("(%d, %d) ", i, j)}
}
// 输出:(0,0) (0,1) (0,2) (1,0)
2. continue:跳过本次迭代
- 作用:跳过当前迭代的剩余语句,直接进入下一次迭代。
示例:打印奇数
for i := 1; i <= 10; i++ {if i%2 == 0 {continue // 跳过偶数}fmt.Print(i, " ") // 输出:1 3 5 7 9
}
3. goto:无条件跳转(谨慎使用)
作用:跳转到指定标签(Label)处执行代码,可能破坏代码结构,需谨慎使用。
示例:错误处理中的快速跳转
file, err := os.Open("data.txt")
if err != nil {goto ERROR // 跳转到错误处理标签
}
// 处理文件逻辑
file.Close()
returnERROR:
fmt.Println("打开文件失败:", err)