开发者学堂课程【Go 语言核心编程 - 基础语法、数组、切片、Map: for 循环注意事项和细节(2)】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/625/detail/9575
for 循环注意事项和细节(2)
内容介绍
一、注意事项
二、细节讨论
一、注意事项
注意四:Golang 提供 for-range 的方式,可以方便遍历字符串和数组(注:数组的遍历放到讲数组的时候再讲解),案例说明如何遍历字符串。字符串的遍历有两种方式,一种是传统方式遍历,一种是 for-range 方式。
1、字符串遍历方式一
传统方式遍历字符串,不能含中文:
比如定义变量 str 为 string 类型,赋值为 hello,world!,然后传统方式 for 进行遍历,这里 for 中再定义一个i与之前上面已经定义过的i是不冲突的,因为 for 循环中定义的 i 只作用于 for 循环内,循环条件为i小于字符串的长度 len(str),循环迭代为 i++。for 循环中写入 Printf 语句进行打印,格式化输出字符串 str[i] ,加上换行符 \n,i 表示第几个字符,所以 i 要从 0 开始取,初始化为 0。这里的 str[i] 使用到下标,为访问字符串第几个字符,如 i 为 0,str[0] 就等于 h,i 为 1,str[1]就等于 e,下面运行一遍:
代码如下:
var str string=“hello,world!”
for i := 0;i< len(str);i++{
fmt.Printf(“%c\n”,str[i])
//使用到下标...
}
运行结果:
2、字符串遍历方式二
for-range 方式:
代码如下:
…
fmt.Println()
//为了与上面进行区别增加换行
str=”abc~ok”
//字符串为 abc~ok,相当于上面 hello,world 遍历完后将 str 改为了 abc~ok
for index,val :=range str{
// index 为下标
fmt.Printf(“index=%d val=%c\n”,index,val)
//打印 index,val 进行查看
}
运行结果:
index 下标为 0,相当于第一次从 str 中取出的时候字符为 a,第二次为 b ,以此类推直到 k,而在取字符的时候 index 按照顺序变化,从 1 到 5,相当于 index 从 str 中取出第一个字符,把 a 交给 val,a 对应的字符串下标则等于 0,然后进行第二次遍历,将 b 交给 val,b 对应的下标为 1,剩下的也是这么理解。下面通过图示再进行讲解。
如下图,字符串 str 在内存中存放的时候都对应的一个小房间,从 0 开始编号,每个小房间都有一个编号,而 str[2] 则表示第二个小房间对应的字符,就等于 c。每次从 str 中取值的时候就把值分别交给 index 和 val,index 是编号。
str=“abc ok”
[a|b|c]~|o|k]
0 1 2 3 4 5
Str[2]==>|c
注意: for-range 在遍历字符串时,只按照字符来遍历,而不是按照字节来的,请注意这一点。
二、细节讨论
如果字符串中有中文,如 string =“hello,world! 北京”,此时再运行代码会发现取值到!后,再取北京则会出现乱码。
原因是如果字符串中有中文,则传统的写法默认是按照字节进行遍历,也就是一个字节一个字节的进行遍历,而 Golang 语言是按照 utf-8 编码,一个汉字对应三个字节,就相当于取值只取了三分之一。
解决方式:只需要将 str 转成 []rune 切片(切片会在数组的切片章节进行讲解)。
代码为:
var str string = “hello,world!北京”
str2 := []rune(str)
//强制把 str 转成 []rune,[]rune 是新的类型,为切片。因为 str 类型本身就是 str 字符串,而 []rune 类型转为 str 类型不统一,所以这里要用新的变量 str2 进行接收。
for i := 0;i < len(str2);i++{
fmt.Printf(“%c \n”,str2[i])
//使用到了下标
}
运行结果:
那么如果通过 for-range 方式进行打印“abd~ok上海“ 则不会乱码,代码为:
str=”abc~ok上海”
for index,val :=range str{
fmt.Printf(“index=%d val=%c\n”,index,val)
}
运行结果:
可以观察到 index 从 6 跳到了 9 ,正是因为汉字“上”占 3 个字节,为 6,7,8,到第九个字节就为海。因为 for-range 这种方式是智能的,按照字符方式进行遍历,就算有中文在 str 字符串内也是可以正常输出的,所以推荐使用这种方式遍历。