流程控制(循环语句)
💥本文章所有相关go代码参考自go 1.18+版本
for计数器迭代
|
|
- 由三部分组成循环的头部,相互之间使用英文分号(
;
)隔开,但并不需要括号将它们括起来。 - 区别其他语言形式如【
for (初始化语句; 条件语句; 修饰语句) {}
】其实使用括号包起来也可以。
同时使用多个计数器
- 这得益于
Go
语言具有平行赋值的特性。 - 区别总结:
for
关键字后面不需要括号。- 初始化语句和修饰语句可以使用平行赋值的特性。
|
|
for{}
- 可以认为这是没有【初始化语句】和【修饰语句】的
for
结构,因此;;
便是多余的了。 - 即使是条件语句也可以省略,如【
i: = 0; ;i++
】或【for {} 或 for ;; {}
】多余的;;
会在使用时移除,这些循环的本质就是无限循环。 - 也可以写成【
for true {}
】一般都是直接写成【for {}
】。 - 如果
for
循环的头部没有条件语句,默认为true
和switch
没有表达式类似默认为true
。- 一般
Go
处理类似情况的常用法则,因此循环体内必须有相关的条件判断以确保会在某个时刻退出循环。
- 一般
- 区别总结:
- 【
for {}
】我们可以理解为【for 条件语句 {}
】这种形式,省略了初始化语句和修饰语句,与其他语言【while (true) {}
】用法类似。
- 【
|
|
使用示例
|
|
|
|
|
|
判断一个数是否是质数
|
|
for-range
- 【
for - range
】结构是Go
语言特有的一种迭代结构,它在许多情况下都非常有用。 - 可以迭代任何一个集合,也包括数组(
array
)和字典(map
)和字符串(string
)和通道(channel
)和切片(slice
),同时可以获得每次迭代所对应的索引和值。
|
|
- 如果只需要
range
里的索引值,可以只写key
省略value
。
|
|
val
值始终为集合中对应索引的副本,因此它一般只具有只读性质。- 对它所有的任何修改都不会影响到集合中原有的值。
- 如果
val
为指针,则会产生指针的副本,依旧可以修改集合中的原值。 range
遍历的也是副本。
for
循环的range
格式可以对slice
、map
、array
、string
、chan
等进行迭代循环。Golang
的range
类似迭代器操作,返回【(索引, 值
) 】或【(键, 值
)】。
类型 | key | value | 描述 |
---|---|---|---|
string |
index 是 int 类型 |
s[index] 是 rune 类型 |
字符串 |
array/slice |
index 是 int 类型 |
s[index] 是存储的元素类型 |
数组/切片 |
map |
key |
m[key] 是map 存储类型 |
字典,遍历顺序是随机的 |
channel |
element 是chan 存储类型 |
通道 |
- 可以忽略不想要的返回值,或使用
_
这个特殊变量。注意_
是内置已经声明的,因此不能使用这种形式_:=1
,不能使用:=
应该使用=
。
使用示例
|
|
for-range
会拷贝遍历对象
- 注意下面的代码
range
复制了a
对象数据所以输出结果和预期的不同。
|
|
for-range
遍历切片
- 改用引用类型,其底层数据不会被复制,注意下面代码。
- 另外两种引用类型
map
、channel
是指针包装,而不像slice
是struct
。
|
|
for-range
遍历字符串
- 字符串是
Unicode
编码的字符集合使用for-range
结构迭代字符串。
|
|
注意
- 遍历切片:下面程序上有没有可优化的空间?
|
|
- 解析:使用 range 遍历,每次迭代会对 index,value 进行赋值,若数据很大或 value 类型为 string 时,对 value 的赋值操作可以进行优化,即忽略 value 值,使用 slice[index] 来获取 value 的值。
- 解析:使用 range 遍历,每次迭代会对 index,value 进行赋值,若数据很大或 value 类型为 string 时,对 value 的赋值操作可以进行优化,即忽略 value 值,使用 slice[index] 来获取 value 的值。
|
|
- 动态遍历:下面程序上能否正常结束?
|
|
- 解析:会正常结束。循环内再改变切片的长度,不影响循环次数,循环次数在循环开始前就已经是确定了的。
- 遍历Map:下面程序上有没有可优化的空间?
|
|
- 解析:使用 range 遍历,根据第一题经验,我们根据 key 值来获取value 的值,看似减少了一次赋值,但使用 mapTest[key] 来获取 value 值的性能消耗可能高于赋值消耗。能否优化取决于 map 所存储数据结构特征,应结合实际情况进行。
- 我们知道mapTest[key]的取值是一个非常复杂的函数调用,mapTest[key]的使用反而会增加负担。