rune

2021-04-20  本文已影响0人  JunChow520

Unicode

Unicode统一码又称为万国码或单一码,是计算机科学领域中的一项业界标准,包含字符集、编码方案等。

Unicode统一码是为了解决传统字符编码方案的局限而产生,它为每种语言中每个字符设定了统一且唯一的二进制编码,以满足跨语言、跨平台进行文本转换和处理的要求。

Unicode统一码是基于通用字符集(Universal Character Set)标准发展而来的,Unicode字符集简称为UCS(Unicode Character Set),早期的Unicode标准有UCS-2、UCS-4说法。

Unicode编码系统可分为编码方式和实现方式两个层次

编码方式上,Unicode是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案,采用数字0到0x10FFFF来映射所有的字符,最多可容纳1114112个字符。从数字0开始为每个符号会指定一个编号,这个编号叫做Code Point,翻译为码元、码位、码点都有,都是指可以分配给字符的数字。码点规定使用U+随后紧接着十六进制数来表示。

例如:Unicode码点0的符号是null,表示所有二进制位都是0。

U+0000 = null

目前最新版的Unicode7.0共收录了109449个符号,中日韩文字位74500个,东南亚文字占了全球现有符号的2/3。如此多的符号Unicode并不是一次性定义的,而是采用分区定义的方式。规定每个区可存放65536个字符,一个区又称为一个平面(plane),目前共有17个平面。在所有字符为最前面的65535个字符位称为基本平面(BMP),码点范围从0到65535,十六进制表示从U+0000到U+FFFF。基本平面存放着最常用的字符,这也是Unicode最先定义和公布的一个平台。剩余字符都存放在辅助平面(SMP),码点范围U+010000到U+10FFFF。

实现方式上,Unicode指规定了每个字符的码点,具体采用什么样的字节序表示码点就涉及到了编码方法。编码方式目的将数字表示为程序中数据,最直观的编码方法是每个码点使用4个字节表示,字节内容一一对应码点,这种编码方法就叫做UTF-32。

比如:码点0的UTF-32表示方式

U+0000 = 0x00 00 00 00

UTF-32编码方案的优点在于,转换规则简单直观,查找效率高,时间复杂度O(1)。缺点在于浪费空间,同样内容的英文文本会比ASCII编码大4倍。这个缺点很致命,导致实际上没有人使用,比如HTML5标准就明文规定,网页编码不得采用UTF-32。


UTF是UCS Transformation Format的缩写,翻译为Unicode字符集转换格式,即怎样将Unicode定义的数字转换称为程序数据。

UTF-8

为了节省空间就导致了UTF-8的诞生,UTF-8是一种变长的编码方法,字符长度从1个字节到4个字节不等。越是常用的字符,字节越短,最前面的128个字符只使用1个字节表示,与ASCII码完全相同。

UTF-8又称为8位元,是针对Unicode的一种可变长度字符编码。可以用来表示Unicode标准中的任何字符,其编码中的第一个字节仍与ASCII相容。

UTF-8使用1到4个字节为每个字符编码

byte

字节是计算机用于计量存储容量的一种单位,是二进制数据的单位,一个字节通常8位长。Go语言中byteuint8类型的别名,一个字节存储8位无符号数,存储的数值范围从0到255。byte可用于表示ASCII码表中的一个字符,传统ASCII编码的字符每个只占1字节。

数据类型 别名 数据范围 描述
uint8 byte 0~255 可表示ASCII字符

例如:ASCII码表中大写字母A对应的十进制数值为65,对应十六进制数值为41。

var b byte = 65
fmt.Printf("ascii = %v, unicode = %U, char = %c, hex = %x\n", b, b, b, b)
// ascii = 65, unicode = U+0041, char = A, hex = 41

注意:格式化说明符%c表示字符(char),当与字符配合使用时%v%d会输出字符对应的整数,%U输出格式为U+hhhh的字符串。

char

和其它语言不同的是Go语言中没有字符这种数据类型,字符只是整数的特殊用例。在Go中具两个用来表示字符的整型别名分别是byterune

type byte = uint8
type rune = int32

既然byterune都能表示字符,为什么还需要两种呢?由于byte占用1个字节,因此可用来表示ASCII字符。Go默认编码方式为UTF-8,UTF-8采用的是变长的编码方式,字符长度从1到4个字节不等。对于具有2个字节以上的字符,此时byte就无能无力了。因此就需要rune

string

Go语言中字符串string本质上是一个只读的字节切片,由于是只读的因此字符串内容一旦被创建是不能被修改的。如需修改需将字符串先转换为[]byte字节切片或[]rune符文切片再操作。

当使用for...range遍历字符串时,Go会自动将字符串转换为[]rune后再执行遍历,即按字符遍历。而使用for循环字符串时,不会发生自动转换,默认会按字节遍历。

例如:按字节遍历字符串

s := "字符串str"
for i := 0; i < len(s); i++ {
    fmt.Printf("%+v %c\n", s[i], s[i])
}
229 å
173 ­
151 �
231 ç
172 ¬
166 ¦
228 ä
184 ¸
178 ²
115 s
116 t
114 r

例如:按字符遍历字符串

//字符遍历
s := "字符串str"
for i, v := range s {
    fmt.Println(i, v, fmt.Sprintf("%c", v))
}
0 23383 字
3 31526 符
6 20018 串
9 115 s
10 116 t
11 114 r
上一篇 下一篇

猜你喜欢

热点阅读