在 Go 中字符串是一个使用频率很高的数据类型,通常的操作有拼接和切片操作,拼接操作不是这篇文章的重点,这里就不做深入讨论,这里聊聊字符串的切片操作。
切片
字符串的长度
先看个简单的例子
package main
import "fmt"
func main() {
sample := "你好,世界"
fmt.Printf("len:%d\n", len(sample))
for index, value := range sample {
fmt.Printf("%d,%q\n", index, value)
}
}
结果应该是多少?5 吗?
len:15
0,'你'
3,'好'
6,','
9,'世'
12,'界'
其他语言的字符串表现
是不是与其他语言的有所区别?比如 Python
>>> a = "你好,世界"
>>> len(a)
5
出现这种现象的本质原因是因为 string 在 Go 的实现方式有关,在 Go 中 string 其实只是一个可读的字节数组切片而已,是不是真的是这样?我们用 Python 的 bytearray 验证一下:
>>> b = bytearray()
>>> b.extend(a.encode())
>>> b
bytearray(b'\xe4\xbd\xa0\xe5\xa5\xbd\xef\xbc\x8c\xe4\xb8\x96\xe7\x95\x8c')
>>> len(b)
15
符合预期,也侧面论证了上面的观点
切片
在了解到 Go 中字符串长度并不是简单的像 Python 等语言那样,显然切片也不能直接根据肉眼看到的字符串长度进行切片,比如上面的例子中sample[:2]
显然结果不太可能是 "你好"
找到对应的 Index 然后切片是个可行的办法,但是显然不是一个好办法
有没有更简单的办法?有的,使用 rune
package main
import (
"fmt"
)
func main() {
sample := "你好,世界"
fmt.Println(string([]rune(sample)[:2]))
}
结果输出:
你好
总结
出现上面现象的原因本质是因为编码问题,Go 默认是 UTF-8
的编码,但是汉字显然不在其列,所以导致显示异常,而 rune
则代表着 Unicode
编码,因而变现正常起来。