首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Rune与字符串上的字节之间的关系

Rune与字符串上的字节之间的关系
EN

Stack Overflow用户
提问于 2019-10-31 00:43:25
回答 3查看 6.6K关注 0票数 20

根据https://blog.golang.org/strings和我的测试,看起来当我们range一个字符串时,我们得到的字符是rune类型,但是如果我们通过str[index]得到它,它们将是byte类型,为什么呢?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-10-31 01:38:18

对于第一个层次,原因是因为这是如何定义语言字符串类型告诉我们:

字符串值是(可能为空的)字节序列。字节数称为字符串的长度,从不为负数。字符串是不可变的:一旦创建,就不可能更改字符串的内容。

以及:

整数索引0可以通过len(s)-1访问字符串的字节。

同时,range是一个可以插入到语句中的子句,规范说:

" range“子句中右边的表达式称为范围表达式,它可能是.一根绳子。

以及:

  1. 对于字符串值,"range“子句从字节索引0开始遍历字符串中的Unicode代码点。在连续迭代时,索引值将是字符串中连续UTF-8编码的代码点的第一个字节的索引,第二个值的类型为rune,将是相应的代码点的值。如果迭代遇到无效的UTF-8序列,第二个值将是0xFFFD,Unicode替换字符,下一个迭代将在字符串中前进一个字节。

如果你想知道为什么语言是这样定义的,你真的必须问定义者自己。但是,请注意,如果for仅位于字节上,则需要构造自己的高级循环才能在代码中进行范围。考虑到for ... range确实在运行脚本,如果您想使用字符串s中的字节,则可以编写:

代码语言:javascript
复制
for i := 0; i < len(s); i++ {
    ...
}

并且很容易在循环中访问s[i]。你也可以写:

代码语言:javascript
复制
for i, b := range []byte(s) {
}

并访问循环中的索引i和字节b。(从字符串到[]byte的转换(反之亦然)可能需要一个副本,因为[]byte可以修改。但是,在这种情况下,range不会修改它,编译器可以优化副本。见icza的评论如下这个答案 to (串).)所以你没有失去任何能力,也许只是一个简洁的斯米琴

票数 17
EN

Stack Overflow用户

发布于 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返回,然后转移到下一个字节。

票数 13
EN

Stack Overflow用户

发布于 2021-11-24 13:28:04

只是让你知道。如果您想在string上迭代一个经典的for循环,并使用运算符[]来获得rune,您可以这样做:

代码语言:javascript
复制
{
  rstr := []rune(MyString)
  for idx := 0; idx < len(rstr); idx++ {
    // code before...
    currentRune := rstr[idx]
    _ = currentRune // to avoid unused error
    // code after...
  }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58635507

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档