代码之家  ›  专栏  ›  技术社区  ›  Shaonv

golang中的“range str”和“range[]符文(str)”有什么区别吗

go
  •  1
  • Shaonv  · 技术社区  · 7 年前

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

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

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

    2 回复  |  直到 7 年前
        1
  •  7
  •   jrefior    7 年前

    是的,有区别。鉴于

    for i, c := range v {
    

    c 是否相同 v 是字符串或符文片段,但 i 如果字符串包含多字节字符,则会有所不同。

    字符串索引

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

    范围循环是特殊的

    for i, c := range str {
    

    字符串上的范围循环是特殊的。与其简单地将字符串视为字节片, range 将字符串部分视为字节片,部分视为符文片。

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

    除了Go源代码是UTF-8这一公理化的细节之外,实际上只有一种方法Go专门处理UTF-8,那就是在字符串上使用for range循环。我们已经看到了常规for循环的情况。相反,for-range循环在每次迭代中解码一个UTF-8编码的符文。每次循环时,循环的索引都是当前符文的起始位置,以字节为单位,代码点是其值。

    更多信息,请参见Go官方博客帖子,以上内容摘自: Strings, bytes, runes and characters in Go

        2
  •  7
  •   JimB    7 年前

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

    // 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: '界