Golang 字符串和 rune

2022-11-28
#go #编码

golang logo

在 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 然后切片是个可行的办法,但是显然不是一个好办法

根据 index 切片

有没有更简单的办法?有的,使用 rune

package main

import (
	"fmt"
)

func main() {
	sample := "你好,世界"
	fmt.Println(string([]rune(sample)[:2]))
}

结果输出:

你好

总结

出现上面现象的原因本质是因为编码问题,Go 默认是 UTF-8 的编码,但是汉字显然不在其列,所以导致显示异常,而 rune 则代表着 Unicode 编码,因而变现正常起来。

总结

参考链接