# 7. string
# 7.1 底层
runtime/string.go
type stringStruct struct { str unsafe.Pointer // 指向底层 Byte 数组 len int // String 所占字节数 }
reflect/value.go
type StringHeader struct { Data uintptr Len int }
# 7.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
Unicode & UTF-8
Go 统一使用 UTF-8 编码。
- Unicode 是一种统一的字符集,囊括了 159 种文字的 144679 个字符,14w 个字符至少需要 3 个字节表示,英文字母均排在前 128 个。
- Unicode 每个字符都用 3 个字节来表示,如果字符排在前面,就造成了很多的浪费,于是就出现变长编码 UTF-8:
- 128 个 US-ASCII 字符只需要 1 个字节编码
- 西方常用字符需要 2 个字节编码
- 其他字符需要 3 个字节编码,极少数需要 4 个字节编码
# 7.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
# 7.4 切分
先转为 rune[] 切片,再进行切片切分
s := string([]rune(s)[:3])