string类型值的底层是如何表达的?

  • 一个string类型的值是有一系列向对应的Unicode代码点的UTF-8编码值来表达的

在Go语言中,一个String类型的值既可以拆分成一个包含多个字符的序列,也可拆分成一个包含多个字节的序列

  • 多个字符序列:由一个rune为元素类型的切片表达
  • 多个字节序列:由一个以byte为元素类型的切片表达

rune是Go语言特有的一个基本数据类型,它的一个值就代表一个字符,即:一个Unicode字符

  • ‘G’、 ‘o’、’爱’、’好’、’者’ 代表的就死一个Unicode字符
  • UTF-8 编码方案会把Unicode字符编码为一个长度在[1,4]范围内的字节序列
  • rune类型的生命: type rune = int32 它实际就是int32类型的一个别名类型


  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. str := "Go爱好者"
  7. fmt.Printf("The string: %q\n", str) // Go爱好者
  8. fmt.Printf(" => runes(char): %q\n", []rune(str)) // ['G' 'o' '爱' '好' '者']
  9. fmt.Printf(" => runes(hex): %x\n", []rune(str)) // [47 6f 7231 597d 8005]
  10. fmt.Printf(" => bytes(hex): [% x]\n", []byte(str)) // [47 6f e7 88 b1 e5 a5 bd e8 80 85]
  11. }

从上面示例代码可见:

  • 字符串 “Go爱好者” 如果被转换为 []rune 类型的值,其中每一个字符都是一个独立的rune类型的元素值
  • 每个rune类型的值在底层都是由UTF-8编码值来表达
  • UTF-8 编码的值由 [1,4] 个字节组成,因此最后一句打印的值要比倒数第二句长很多

使用range子句的for语句遍历字符串

  1. str := "Go爱好者"
  2. for i, c := range str {
  3. fmt.Printf("%d: %q [% x]\n", i, c, []byte(string(c)))
  4. }

打印的结果为:

  1. 0: 'G' [47]
  2. 1: 'o' [6f]
  3. 2: '爱' [e7 88 b1]
  4. 5: '好' [e5 a5 bd]
  5. 8: '者' [e8 80 85]


_
每次迭代都会打印出两个值:**_

  • 第二个值是 rune类型的值
  • 第一个值则是 rune类型值的起始字节字符串字节中的位置