范围str https://play.golang.org/p/I1JCUJnN41h
范围[]符文(str) https://play.golang.org/p/rJvyHH6lkl_t
我得到了相同的结果,它们是一样的吗?哪个更好?
答案 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: '界