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