Golang 中的字符串和字符有什么区别?

在 Golang 中,字符串(string)和字符(rune)是两个不同的概念:

  • 字符串(string)是一个字节序列,可以包含任何二进制数据。每个字符串由一个不可变的字节数组表示。
  • 字符(rune)是一个 Unicode 码点,代表一个 Unicode 字符。rune 是 int32 的别名。

也就是说:

  • string 表示文本序列,是以字节为单位的。
  • rune 表示 unicode 字符,是以字符为单位的。

例如:

s := "Hello"        // s的类型为string
c := 'H'            // c的类型为rune,等价于int32

由于 Golang 支持 Unicode,所以一个字符不一定占用一个字节:

s := "你好" 
for i := 0; i < len(s); i++ {        // len(s) = 6
    c := rune(s[i])
    fmt.Printf("%c %d\n", c, c)
}
// 你 20320
// 好 22909

可以看到,中文字符你和好都占3个字节,对应一个rune值。
所以当我们需要以字符为单位处理文本时,应使用rune,其他大部分场景使用string即可:

// 字符串遍历
for i := 0; i < len(s); i++ {   // byte为单位
    fmt.Printf("%c", s[i])
}

// 字符遍历 
for _, c := range []rune(s) {   // char为单位
    fmt.Printf("%c", c)
}

字符串相关的内建函数大多数针对的都是byte,而不是char,所以需要自行处理字符的rune值。

例如:

  • len():返回字符串的byte数,而不是字符数
  • cap():返回字符串的底层数组的cap,以byte为单位
  • 加法拼接字符串:实际是字节序列的拼接

所以,掌握字符串和字符的差异以及处理方式对 Golang 开发者来说是比较重要的。特别是在处理 Unicode 文本及其他语言时,这一点就尤为关键。
需要注意的是,大部分情况下我们可以简单地把字符串当作字符序列来处理,不过一旦需要精确地操作字符,则必须转为 rune 数组或切片后再行处理。