Go 之为什么 rune 是 int32 的别名而不是 uint32 的别名

我对这个问题其实也是一直有疑问的,毕竟像 byte 都是 uint8 的别名。然后找了一些问答资料,不知道还没有没其他更好的解释。

范围足够

在 Unicode 字符集中,一个字符的码点范围是从 U+0000 到 U+10FFFF,共计 1114112 个码点,可以用 32 位的整数类型来表示。 Unicode 转换格式,虽然使用的是 4 字节(32bit),但实际上只用到了 21bit。所以 int32 是足够包含该编码范围的。

扩展兼容

使用 int32 类型能有效避免符号扩展等不必要的类型转换,以及提供向下兼容的能力。

算术运算方便

定义为 int32 是为了方便 rune 类型进行算数运算。

package main

import "fmt"

func main() {
	s := "hello world"
	a := []rune(s)
	fmt.Println(a)
	b := a[1] - a[0]
	if b < 0 {
		fmt.Println(b)
	}
}

比如像 byte 进行算术运算时,就会出现溢出的情况(所以也建议大家尽量不要拿 byte 的运算结果做条件判断等)。

package main

import "fmt"

func main() {
	s := "hello world"
	a := []byte(s)
	fmt.Println(a) // [104 101 108 108 111 32 119 111 114 108 100]
	if a[1] - a[0] > 0 {
		fmt.Println("a[1] > a[0]", a[1] - a[0]) // a[1] > a[0] 253
	}
	if a[0] - a[1] > 0 {
		fmt.Println("a[0] > a[1]", a[0] - a[1]) // a[0] > a[1] 3
	}
}

uint8 别名 byte

既然如此,还有一个疑问,为什么 Go 中 byte 是 uint8 的别名,而不是 int8 的别名呢?

哈哈,这个就不得不提到 UTF-8 编码了,正好也是 Go 默认的编码方式。

UTF-8 最大的一个特点,就是它是一种变长的编码方式。它可以使用 1~4 个字节表示一个符号,根据不同的符号而变化字节长度。

UTF-8 的编码规则很简单,只有二条:

  • 对于单字节的符号,字节的第一位设为 0,后面 7 位为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的
  • 对于 n 字节的符号(n > 1),第一个字节的前n位都设为1,第n + 1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码。
package main

import (
	"fmt"
)

func main() {
	s := "好"
	b := []byte(s)
	fmt.Println(b) // [229 165 189]
	for _, c := range b {
		fmt.Printf("%b ", c) // 11100101 10100101 10111101
	}
}

这样的话,在 UTF-8 编码下使用 byte 表示非 ASCII 字符的话(需要多字节表示),就不得不涉及到字节高位的情况了,而字节高位的表示显然是用 int8 无法处理的。

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-23 19:42:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-23 19:42:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-04-23 19:42:02       82 阅读
  4. Python语言-面向对象

    2024-04-23 19:42:02       91 阅读

热门阅读

  1. 商城数据库----3

    2024-04-23 19:42:02       35 阅读
  2. 02_c/c++开源库 json解析jsoncpp库

    2024-04-23 19:42:02       37 阅读
  3. Linux中安装MySQL数据库(Red Hat7.9安装MySQL5.7数据库)

    2024-04-23 19:42:02       31 阅读
  4. K8s: 在Pod中将configmap数据注入容器

    2024-04-23 19:42:02       34 阅读
  5. iOS 将字符串分割成单个字符| 字符串转成数组

    2024-04-23 19:42:02       28 阅读
  6. flink on k8s部署

    2024-04-23 19:42:02       34 阅读
  7. C# winform 阿特拉斯fp6000拧紧枪开发

    2024-04-23 19:42:02       37 阅读
  8. Go学习路线

    2024-04-23 19:42:02       30 阅读