根据https://blog.golang.org/strings和我的测试,看起来当我们range是一个字符串时,我们得到的字符是rune类型,但是如果我们通过 获取它str[index],它们将是byte类型,这是为什么呢?
只是一个关于为什么以这种方式定义语言的快速简单的答案。
想想符文是什么。Arune代表一个Unicode码位,可以由多个字节组成,根据编码的不同也有不同的表示。
现在想想mystring[i]如果返回 arune而不是 a ,这意味着什么byte。由于不扫描字符串就无法知道每个符文的长度,因此该操作需要每次扫描整个字符串,从而使类似数组的访问需要 O(n) 而不是 O(1)。
如果mystring[i]每次都扫描整个字符串,对于语言用户来说将是非常违反直觉的,并且对于语言开发人员来说也更加复杂。这就是为什么大多数区分 Unicode 字符和字节的编程语言(如 Go、Rust、Python)在索引时只返回字节。
从字符串rune的开头进行迭代时,一次访问一个字符串要简单得多,例如使用range. 连续的字节可以被扫描并组合在一起,直到它们形成一个有效的 Unicode 字符,该字符可以作为 返回rune,然后继续下一个。
对于第一级,原因是因为这就是语言的定义方式。该字符串类型告诉我们:
字符串值是一个(可能是空的)字节序列。字节数称为字符串的长度,永远不会为负数。字符串是不可变的:一旦创建,就不可能更改字符串的内容。
和:
字符串的字节可以通过整数索引 0 到 len(s)-1 访问。
同时,range是一个可以插入到forstatement 中的子句,并且规范说:
“范围”子句中右侧的表达式称为范围表达式,它可能是... [a] 字符串...
和:
- 对于字符串值,“范围”子句从字节索引 0 开始迭代字符串中的 Unicode 代码点。在连续迭代中,索引值将是连续 UTF-8 编码代码点的第一个字节的索引字符串和第二个类型
rune的值将是相应代码点的值。如果迭代遇到无效的 UTF-8 序列,则第二个值将是0xFFFDUnicode 替换字符,下一次迭代将在字符串中前进一个字节。
如果你想知道为什么语言是这样定义的,你真的必须问定义者自己。但是,请注意,如果for仅覆盖字节,则需要构建自己的更高级的循环来覆盖符文。鉴于这for ... range 确实通过符文工作,如果你想通过字符串中的字节工作s,你可以写:
for i := 0; i < len(s); i++ {
...
}
Run Code Online (Sandbox Code Playgroud)
并轻松访问s[i]循环内。你也可以写:
for i, b := range []byte(s) {
}
Run Code Online (Sandbox Code Playgroud)
并访问循环内的索引i和字节b。(从字符串转换为[]byte,反之亦然,可能需要一个副本,因为[]byte可以修改。不过,在这种情况下,range不会修改它,编译器可以优化掉副本。请参阅下面的 icza 评论或对golang 的回答:[ ]字节(串)VS []字节(*字符串)。)所以,你还没有失去任何能力,只是也许点点简洁的。
| 归档时间: |
|
| 查看次数: |
2634 次 |
| 最近记录: |