Go语言中非英文字符串是否仍是只读的byte切片?
问题解答
非英文字符串是否仍然符合「本质是只读byte切片」的表述
该表述完全成立。
Go中所有字符串的底层存储,都是UTF-8编码的只读字节序列,和存储的字符所属语言没有关系。
- 英文ASCII字符的UTF-8编码就是单个
byte,和本身的ASCII值完全一致,所以直接用下标访问就能拿到对应字符的编码值。 - 中文、日文、韩文、阿拉伯文等非英文字符会被编码为多字节的UTF-8序列,这些字节同样存在底层的只读
[]byte结构中,字符串的不可修改特性对这类内容同样生效:你无法直接修改字符串中的任意一个字节,必须先显式转换为可写的[]byte类型,修改完成后重新转换为字符串,得到的是全新的字符串实例。
能否认为非英文字符串是只读Rune切片
该结论完全不成立,这个误解混淆了「底层存储结构」和「语法层面的遍历便利」:
rune是int32的别名,用于表示单个Unicode码点,它本身是4字节定长的类型。- Go字符串底层从未存储过
rune序列,我们用for range遍历字符串时能直接拿到每个字符对应的rune,是Go运行时自动对底层UTF-8字节做了解码处理,属于语法糖,不代表底层存储结构就是[]rune。
你可以通过两个简单的特性验证这一点:
s := "你好Go" // 1. len()直接计算字符串拿到的是字节数,不是字符数 fmt.Println(len(s)) // 输出 8:"你好"各占3字节,加上2个英文字母共 3*2+2=8 // 2. 用下标直接访问字符串元素,拿到的是byte类型的UTF-8编码值,不是rune fmt.Printf("%#v\n", s[0]) // 输出 0xe4,是"你"的UTF-8编码第一个字节,不是"你"的Unicode码点0x4f60
如果要拿到字符串中每个字符的rune值,必须显式将字符串转换为[]rune类型,这个转换过程会重新分配内存、将UTF-8字节逐个解码为rune存入新的切片,和原字符串的底层存储完全独立。
内容的提问来源于stack exchange,提问作者Parry Wang
相关产品推荐
相关产品推荐

