3 回答
TA贡献1877条经验 获得超6个赞
对于第一级,原因是因为这就是语言的定义方式。String类型告诉我们:
字符串值是一个(可能为空)字节序列。字节数称为字符串的长度,并且永远不会是负数。字符串是不可变的:一旦创建,就不可能更改字符串的内容。
和:
字符串的字节可以通过整数索引 0 到 len(s)-1 来访问。
同时,range
是一个可以插入到for
语句中的子句,并且规范说:
“range”子句右边的表达式称为范围表达式,它可以是... [a] string ...
和:
对于字符串值,“range”子句从字节索引 0 开始迭代字符串中的 Unicode 代码点。在连续迭代中,索引值将是连续 UTF-8 编码代码点的第一个字节的索引字符串和类型为 的第二个值
rune
将是相应代码点的值。如果迭代遇到无效的 UTF-8 序列,则第二个值将为0xFFFD
Unicode 替换字符,并且下一次迭代将在字符串中前进一个字节。
如果你想知道为什么语言是这样定义的,你真的必须问定义者本身。但是,请注意,如果for
仅在字节范围内进行调整,则您需要构建自己的更高级的循环来在符文范围内进行调整。鉴于这for ... range
确实可以通过符文进行操作,如果您想通过字符串中的字节进行操作s
,您可以编写:
for i := 0; i < len(s); i++ { ... }
并轻松访问s[i]
循环内部。你也可以写:
for i, b := range []byte(s) { }
并在循环内访问索引i
和字节。b
(从 string 到 的转换[]byte
,反之亦然,可能需要一个副本,因为[]byte
可以修改。但在这种情况下,range
不会修改它,编译器可以优化掉副本。
TA贡献1802条经验 获得超4个赞
只是一个快速而简单的答案,说明为什么以这种方式定义语言。
想想符文是什么。Arune
代表一个Unicode码点,可以由多个字节组成,根据编码的不同也有不同的表示形式。
现在想想mystring[i]
如果返回 arune
而不是 a ,那么这样做意味着什么byte
。由于如果不扫描字符串就无法知道每个符文的长度,因此该操作需要每次扫描整个字符串,从而使类似数组的访问需要 O(n) 而不是 O(1)。
mystring[i]
如果每次都扫描整个字符串,对于该语言的用户来说是非常违反直觉的,对于语言开发人员来说也更加复杂。这就是为什么大多数编程语言(如 Go、Rust、Python)区分 Unicode 字符和字节,有时仅支持字节索引。
当从字符串的开头迭代时,一次访问一个字符串rune
要简单得多,例如使用range
. 可以扫描连续的字节并将其分组在一起,直到它们形成可以作为 返回的有效 Unicode 字符rune
,然后继续处理下一个字节。
TA贡献1796条经验 获得超7个赞
只是让你知道。如果您想使用经典的 for循环迭代string并使用运算符[]来获取rune,您可以执行以下操作:
{
rstr := []rune(MyString)
for idx := 0; idx < len(rstr); idx++ {
// code before...
currentRune := rstr[idx]
_ = currentRune // to avoid unused error
// code after...
}
}
- 3 回答
- 0 关注
- 116 浏览
添加回答
举报