根据https://blog.golang.org/strings和我的测试,看起来当我们range一个字符串时,我们得到的字符是rune类型,但是如果我们通过str[index]得到它,它们将是byte类型,为什么呢?
发布于 2019-10-31 01:38:18
对于第一个层次,原因是因为这是如何定义语言。字符串类型告诉我们:
字符串值是(可能为空的)字节序列。字节数称为字符串的长度,从不为负数。字符串是不可变的:一旦创建,就不可能更改字符串的内容。
以及:
整数索引0可以通过len(s)-1访问字符串的字节。
同时,range是一个可以插入到语句中的子句,规范说:
" range“子句中右边的表达式称为范围表达式,它可能是.一根绳子。
以及:
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。(从字符串到[]byte的转换(反之亦然)可能需要一个副本,因为[]byte可以修改。但是,在这种情况下,range不会修改它,编译器可以优化副本。见icza的评论如下或这个答案 to (串).)所以你没有失去任何能力,也许只是一个简洁的斯米琴。
发布于 2019-10-31 01:48:42
简单快速地回答一下为什么语言是这样定义的。
想想什么是符文。rune表示一个Unicode代码点,它可以由多个字节组成,并且根据编码也有不同的表示形式。
现在想想,如果mystring[i]返回了一个rune而不是一个byte,那么它意味着什么。因为如果不扫描字符串,就无法知道每个符文的长度,因此该操作将要求每次扫描整个字符串,从而使类似数组的访问采用O(n)而不是O(1)。
如果mystring[i]每次扫描整个字符串,对于语言的用户来说,这将是非常违反直觉的,而且对于语言开发人员来说也更加复杂。这就是为什么大多数编程语言(如Go、Rust、Python)区分Unicode字符和字节,有时只支持字节索引。
相反,每次访问一个rune的字符串在迭代时要简单得多,比如使用range。可以扫描连续字节并将其分组,直到它们形成一个有效的Unicode字符,该字符可以作为rune返回,然后转移到下一个字节。
发布于 2021-11-24 13:28:04
只是让你知道。如果您想在string上迭代一个经典的for循环,并使用运算符[]来获得rune,您可以这样做:
{
rstr := []rune(MyString)
for idx := 0; idx < len(rstr); idx++ {
// code before...
currentRune := rstr[idx]
_ = currentRune // to avoid unused error
// code after...
}
}https://stackoverflow.com/questions/58635507
复制相似问题