likes
comments
collection
share

Go中的rune

作者站长头像
站长
· 阅读数 17

rune类型是文字符号,它是int32类型的别名。

刚开始看到Go的rune类型的时候,我感到很迷惑,在JavaScript和Python中,字符就是字符,整数就是整数,但是在Go中,rune表示文字字符,却又是int32类型的别名。

仔细了解后就会觉得合理了,先从字符编码的方式开始说起:

一开始计算机使用的是ASCII码,ASCII码用7位表示128个字符,包含英文字母,标点符号和数字等:

Go中的rune (图片来源:ASCII码对照表)

显然,ASCII码并不能表示除了英语之外的其他语言,比如中文,所以Unicode编码出现了,它整理、编码了世界上大部分的文字系统。Unicode至今仍在不断增修,每个新版本都加入更多新的字符。

Go的代码使用的是UTF-8的编码方式。UTF-8(8-bit Unicode Transformation Format)是一种针对Unicode的可变长度字元编码,它可以用一至四个字节对Unicode字符集中的所有有效编码点进行编码:

UTF-8所需字节注释
0zzzzzzz(00-7F)1个字节ASCII字元范围,位元组由零开始
110yyyyy(C0-DF) 10zzzzzz(80-BF)2个字节第一个位元组由110开始,接著的位元组由10开始
1110xxxx(E0-EF) 10yyyyyy 10zzzzzz3个字节第一个位元组由1110开始,接著的位元组由10开始
11110www(F0-F7) 10xxxxxx 10yyyyyy 10zzzzzz4个字节将由11110开始,接著的位元组由10开始

使用ASCII码的时候,所有的字符都可以用1字节就能表示,但是使用UTF-8编码的时候,有的字符不止有1字节。

接下来进行一个小练习,打印出字符串中的单个字符。

注意,Go中的len方法返回的是字符串的字节数,不是包含的字符的数量。

  1. 打印只包含英文字母和数字的字符串中的字符:
	s1 := "abc123"
	for i := 0; i < len(s1); i++ {
		fmt.Printf("%c\n", s1[i])
	}

打印结果:

a
b
c
1
2
3
  1. 打印包含中文的字符串中的字符:
	s2 := "a写点啥"
	for i := 0; i < len(s2); i++ {
		fmt.Printf("%c\n", s2[i])
	}

打印结果:

a
å


ç

¹
å

¥

除了a是正常打印出来的,中文打印的都是奇怪的符号。因为是一字节一字节的取值,取的位置不对,所以打印的结果不正确,稍微修改下打印语句,把取到的值的二进制数字也打印出来:

	s2 := "a写点啥"
	for i := 0; i < len(s2); i++ {
		fmt.Printf("%c %[1]b \n", s2[i])
	}

Go中的rune

可以看出“写”,“点”,“啥”每个Unicode码占用的是3字节,而不是1字节,所以取到的值有问题。要正常打印出值,应该分别这样取值:

	fmt.Printf("%c\n", s2[0])
	fmt.Printf("%v\n", s2[1:4])
	fmt.Printf("%v\n", s2[4:7])
	fmt.Printf("%v\n", s2[7:10])

打印结果:

a
写
点
啥

遍历的时候需要先得到字符占用的字节数量,然后根据占用的字节数量取到对应的值,这很不方便。

使用rune类型的话,不论这个字符占用的是几字节,它都表示一个字符。

	s2 := "a写点啥"
	s3 := []rune(s2)
	fmt.Println(len(s2)) // 10
	fmt.Println(len(s3)) // 4
	for i := 0; i < len(s3); i++ {
		fmt.Printf("%c\n", s3[i])
	}

打印内容:

10
4
a
写
点
啥

rune类型是 用于表示字符的Unicode代码点的int32整数的类型, 所以它表示的是文字符号的类型。

另外,如果只是想要遍历字符的话,可以直接用range:

	s4 := "a写点啥"
	for i, value := range s4 {
		fmt.Printf("%d %c\n", i, value)
	}

打印内容:

0 a
147

参考地址

zh.m.wikipedia.org/zh-hans/Uni…

zh.m.wikipedia.org/zh-hans/UTF…

转载自:https://juejin.cn/post/7173133571266347039
评论
请登录