这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天
这篇文章是我个人学习课程之后的一些细节补充:
关于字符串中len()&UTF-8编码
在第一节的课程讲解字符串string的部分中,我们可以看到这个字符串b虽然只放了两个中文字符“你好”但是在使用len函数统计字符长度时显示为6,这完全不符合我们的日常使用认知。
这个问题其实牵扯到go使用的UTF-8编码。我们知道函数len()是直接计算字节数的,也就是说这两个中文字符一共占用了六个字节。而UTF-8编码中恰好使用三个字节来表示一个中文字符。我们先从Unicode讲起:
Unicode是一种单字符编码。支持多种语言,在统一的格式下,每个字符对应一个唯一的二进制编码,以方便各不同平台进行文本处理。
Unicode只规定了各个字符的二进制编码,却没有规定这个符号如何储存。如果没有为计算机规定相应的识别方法,由于每个字符使用的存储长度不固定,计算机无法精确地按照我们的需求进行分割得到所需的字符。中文字符“剔”使用的Unicode编码为\u5254,但计算机没办法直接根据你的想法来判断到底你是想要一个中文字符“剔”,还是两个ASCII字符0x52(R)和0x54(T)?
因此,需要一种编码方式以恰当的方式让计算机正确识别获得我们需要的Unicode字符,这就是UTF(Unicode Transformation Format)。
在go中,使用的是UTF-8编码方式——这是一种变长的编码方式:单字节编码方式和ASCII一致。 多字节编码则满足字节数为N时,第一个字节的前N位为1,第N+1位为0,后面的N-1个字节的前两位都为10,N字节中的其余位全部用来存储Unicode中的码位值。
汉字在Unicode中位于U+0800 ~ U+FFFF范围内,通过UTF-8编码后,就占用了三个字节了,这也就是为什么字符串“你好”用len()函数会返回6。
如果我们需要一个符合日常习惯的结果,可以使用Go 语言中 UTF-8 包提供的 RuneCountInString() 函数,该函数统计 Uncode 字符数量,也就是RuneCountInString(“你好”)返回结果为2。
关于随机数生成&种子
我们能从这里看到,每一次生成的数字都是相同的——不难猜测rand.Intn是一个由确定的随机数生成算法来生成伪随机数的函数。
由官方文档可得,Intn() 函数是由default Source生成随机数。如果不使用func Seed(seed int64)函数对default Source进行修改,会默认Seed=1,那么确定的算法当然会一直生成确定的数字。因此,课程中会使用每时刻不同的系统时间作为种子来生成随机数。
当然,如果需要一个更安全的真随机数生成器,可以使用crypto/rand包,如其中的func Read(b []byte) (n int, err error)函数。