golang中'range str'和'range [] rune(str)'之间有什么区别吗?

时间:2018-03-02 02:54:40

标签: go

范围str https://play.golang.org/p/I1JCUJnN41h

范围[]符文(str) https://play.golang.org/p/rJvyHH6lkl_t

我得到了相同的结果,它们是一样的吗?哪个更好?

2 个答案:

答案 0 :(得分:6)

是的,有区别。给定

for i, c := range v {
无论c是字符串还是符文切片,

v都是相同的,但如果字符串包含多字节字符,则i会有所不同。

字符串索引

字符串是字节序列,索引适用于一片字节。除非您有意读取或操作字节而不是代码点或字符,或者确保您的输入不包含多字节字符,否则无论您何时倾向于索引字符串,都应使用符文切片。

范围循环是特殊的

for i, c := range str {

字符串上的范围循环是特殊的。 range不是简单地将字符串视为一个字节片段,而是将字符串视为一片字节,部分像一片符文。

i将是代码点开头的字节索引。 c将是一个可以包含多个字节的符文。这意味着i在迭代中可以增加多个,因为先前的代码点是多字节字符。

  

除了Go源代码为UTF-8的公理细节之外,Go实际上只有一种方式特别是对待UTF-8,那就是在字符串上使用for range循环时。我们已经看到了常规for循环会发生什么。相反,对于范围循环,在每次迭代时解码一个UTF-8编码的符文。每次循环时,循环的索引是当前符文的起始位置,以字节为单位,代码点是其值。

在官方Go博客文章中查看更多内容,摘自:Strings, bytes, runes and characters in Go

答案 1 :(得分:4)

您获得相同的结果只是因为您没有包含任何多字节字符,并忽略了索引。

// ranges over rune as indexed in the string
for i, r := range s {

// ranges over runes as indexed in the []rune
for i, r := range []rune(s)

例如:https://play.golang.org/p/ZLCc3UNL2dR

s := "こんにちは世界"

fmt.Println("range s")
for i, r := range s {
    fmt.Printf("%d: %q\n", i, r)
}

fmt.Println("\nrange []rune(s)")
for i, r := range []rune(s) {
    fmt.Printf("%d: %q\n", i, r)
}

打印

range s
0: 'こ'
3: 'ん'
6: 'に'
9: 'ち'
12: 'は'
15: '世'
18: '界'

range []rune(s)
0: 'こ'
1: 'ん'
2: 'に'
3: 'ち'
4: 'は'
5: '世'
6: '界