


视频: https://www.bilibili.com/video/BV1XV411Y7h7/

在上节,我们首次接触到了循环结构,并得知在Golang中只有一种循环——For循环
下面要介绍另一种循环,实际上它是For循环的另一种格式,所以与上面的说法并不矛盾
For-Range循环用于遍历Golang中不同的数据类型,它们分别是:
数组(array)/切片(slice)
字符串(string)
字典(map)
通道(channel)
因为到目前为止,我们只接触过字符串,所以下面对For-Range的讨论由字符串展开
后面学到对应的数据类型时,我们会重新拾回For-Range,所以Don’t worry~

下面是For-Range循环遍历字符串时的完整格式:

注意到上图分别短声明了两个变量index/value,短声明的右边是range关键词加某个字符串
当然也是有For循环局部作用域的问题,index/value只能在For循环内使用
index与value都是可选的
在开始接触For-Range之前,我们需要稍微了解一些字符串编码的知识
字符串是编程之旅中最常用的基本数据类型之一,但事实上,它也并没有那么的基本,因为它是由字节(byte)组成的一个序列
通过Golang内置函数,我们可以得知一个字符串占了多少字节:

这个字符串占了5个字节,没毛病啊,因为它一共只有5个字符
再看看一个包含中文的字符串的长度:

Whattt??? 结果显示是11,但是明明只有7个字啊?? 我悟了,原来计算机还没我聪明

在Golang中,字符采用Unicode字符集表示(万国码,可以表示全世界的文字),用UTF-8规则进行编码,像这些ASCII字符用1个字节表示,其余字符用1~4个字节表示
在上面的中文例子中:
"nbody"有5个英文字符,占5个字节
一个中文字符用3个字节表示,所以"编程"占了6个字节
5+6=11,所以len(s)的结果是11
遍历的意思是,比如有一个字符串,我将它的每一个字符、、、、访问个遍
所以现在的问题是,如何访问一个字符串的其中一个字符?答案是: 利用它的索引(index)访问即可
所谓索引,就是在里面的位置,它是0,的位置是1,的位置是4。索引是从0开始计数的
通过这样的格式就可以访问它的某个字符:

等等,为什么输出的是一堆数字?这里要追溯到基本数据类型一节中,我们曾介绍了两个很特别的类型:

byte(字节类型)是uint8的别名
rune(代表一个Unicode字符)是int32的别名
也就是说一个字节实际上就是一个8位的无符号整数,所以我们看到的是一堆数字
我们需要将数字转换成它对应的Unicode字符,可以利用函数与标记:

再利用上节所学的For循环,就可以遍历一个字符串了:

两种格式的区别主要在于,遍历字符串时的行为不同:
For-Standalone会遍历字符串的每一个字节(Byte类型)
For-Range会遍历字符串的每一个Unicode字符(Rune类型)
下面通过一个例子来理解,我们把上一个例子换成包含中文的字符串:

最后输出了6个乱码,这是因为For-Standalone格式的循环会遍历每一个字节,但最后6个字节是每3个字节表示一个中文字符,这里把它拆分了,所以输出乱码
用For-Range格式来遍历:

标记表示输出一个整数,可以看到,For-Range同时遍历了索引和对应的Unicode字符
利用标记可以看到迭代时的字符的类型:

所以遍历字符串时,应该用For-Range格式,才能输出正确的rune类型字符
假如只想遍历索引,这时可以无视value,因为value是可选的:

很多情况下,我们只需要遍历value,可以利用iota常量计数器一节中所学的空标识符()来忽略index:

也可以把两者都忽略掉,但很少这样使用:

感觉这节主角其实是For-Range,但大部分内容都是在讲Golang中的字符串编码问题,有点喧宾夺主…
but,如果不讲清楚这个问题,那For-Range就无法展开讨论了 =。=
anyway,有所收获就行~

下节,我们将介绍Golang中的一个异类,利用它,可以构成非常复杂的程序结构。
如果你看过《火影忍者》,你可以称它为Golang中四代火影的拿手好戏——飞雷神之术

goto next_time…
原文地址: https://nbody1996.gitee.io/becoming_gopher/posts/013/