1. 底层

  • runtime/string.go
type stringStruct struct {
	str unsafe.Pointer		// 指向底层 Byte 数组
	len int								// String 所占字节数
}
  • reflect/value.go
type StringHeader struct {
	Data uintptr
	Len  int
}

2. 测试

s_en := "hedonwang"
	s_cn := "王小佳"

	fmt.Println(unsafe.Sizeof(s_en)) //16
	fmt.Println(unsafe.Sizeof(s_cn)) //16
	s_en_sh := (*reflect.StringHeader)(unsafe.Pointer(&s_en))		//16
	s_cn_sh := (*reflect.StringHeader)(unsafe.Pointer(&s_cn))		//16

	fmt.Println(s_en_sh.Len)	//9
	fmt.Println(s_cn_sh.Len)	//9

Go 统一使用 UTF-8 编码。

  • Unicode 是一种统一的字符集,囊括了 159 种文字的 144679 个字符,14w 个字符至少需要 3 个字节表示,英文字母均排在前 128 个。
  • Unicode 每个字符都用 3 个字节来表示,如果字符排在前面,就造成了很多的浪费,于是就出现变长编码 UTF-8:
  • 128 个 US-ASCII 字符只需要 1 个字节编码
  • 西方常用字符需要 2 个字节编码
  • 其他字符需要 3 个字节编码,极少数需要 4 个字节编码

3. 访问

  • fori 去访问 str[i] 访问的是 byte[] 字节数组
str := "王小佳hedonwang"
for i := 0; i < len(str); i++ {
  fmt.Printf("%v ", str[i])
}
// 231 142 139 229 176 143 228 189 179 104 101 100 111 110 119 97 110 103
  • 访问字符需要用 for … range,即访问 rune[] 数组
str := "王小佳hedonwang"
for _, char := range str {
  fmt.Printf("%c ", char)
}
// 王 小 佳 h e d o n w a n g

4. 切分

  • 先转为 rune[] 切片,再进行切片切分
s := string([]rune(s)[:3])