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])