Go原生支持Unicode,字符集与编码的问题在编程语言中是很重要的,尤其对于CJK(中日韩)开发者来说。以前很多开发推荐使用GBK编码,现在更加推荐使用UTF-8,虽然UTF-8编码需要更大的存储空间,但是它带来的便利性实在远超过那一些存储空间。现代语言一般都支持Unicode了。着一篇争取对Unicode,UTF-8,UTF-16,ISO-8859有一个系统的了解。
介绍
最早的计算机系统都是使用 EBCDIC(扩展的二进制的十进制转换码) 和 ASCII 编码,因为那时候只是用一些英文字母数字,加减号和其他一些字符,字符并不多,但是随着Internet的发展,网络遍布全球。全球有大概6000种语言(其中3000种在巴布亚新几内亚…) ,为了更好地服务更多的人,我们需要为不同语言的用户提供不同的语言支持。
如果世界只需要 ASCII 编码,那样将会简单很多。但事实却是非常复杂的,现代项目都应该考虑 i18n 和 l10n, 分别代表 internationalisation 和 localisation。i18n指应用能处理各种各样不同的语言和文化, l10n 则是为某个特定的文化团体定制你的国际化应用。
更广泛的i8n不仅仅是文字编码的区别,还要考虑诸如颜色、音乐在不同语言文化中的不同代表意义。但这个领域太过复杂,暂时一般不考虑。
定义
Character
Character 就是字符,
“the smallest component of written language that has a semantic
value
当然字符也包括自然语言符号之外的一些控制字符。关于字符的内容,可以查看 维基百科
字符集,character code 字符编码就是将一个字符映射到一个整数,比如最常见的 ASCII编码,将 a 编码为 97(编码点,code point), A编码为65.编码仍然是抽象的,它仍不是我们在文本或者TCP包中多见到的。
Character encoding 注意code和encoding是不同的。字符编码(encoding)表示的是其二进制编码。诸如补码,反码等。代表字符 A 在二进制上是怎么存储的。
字符编码(英语:Character encoding)、字集码是把字符集中的字符编码为指定集合中某一对象(例如:比特模式、自然数序列、8位组或者电脉冲),以便文本在计算机中存储和通过通信网络的传递。常见的例子包括将拉丁字母表编码成摩斯电码和ASCII。其中,ASCII将字母、数字和其它符号编号,并用7比特的二进制来表示这个整数。通常会额外使用一个扩充的比特,以便于以1个字节的方式存储。
按照惯例,人们认为字符集和字符编码是同义词。
传输编码/Transport encoding对一段在网络传输的数据需要如何确认它的字符集和编码呢?可以在传输的头部包含一段内容编码信息的内容,就像HTTP头那样。
Content-Type: text/html; charset=ISO-8859-4 |
但是我们要怎么读到这一段内容呢?因为它们也是要编码的,这就是一个现有鸡还是先有蛋的问题了。但是我们可以做一个约定,这些信息都使用 ASCII 编码,更明确一点就是 US ASCII。因为这一部分信息的内容的功能使用ASCII就能搞定了。
常用编码
ASCII
ASCII 编码大家都很熟悉了,大一的时候专业基础课接触到的就是这些内容。作为最常用的编码,ASCII使用的编码点使用7-bit。
ISO 8859
现在一个字节的标准是8个比特位,作为ASCII的扩展多出来128个编码点。一些列不同的编码集使用了这128个编码点,它们被一些欧洲语言使用,合起来就是 ISO-8859系列。 ISO-8859-1也就是常说的Latin-1,它涵盖了大部分的欧洲语言。
ISO-8859是一个系列,系列中所有的低128个编码点就是ASCII编码,以实现兼容。
早期的HTML标准推荐使用ISO-8859-1字符集。不过在 HTML 4 之后就推荐使用 Unicode了。
Unicode
像ASCII和ISO8859这样的编码在象形文字(中日韩)语言面前显得就太小气了。中文常用的字多大几千个,至少需要两个字节才能涵括。最初没有统一的国际标准,因此出现了很多的2字节编码方案,比如台湾的Big5,国内的GB2312,BGK;再考虑日本的JIS X 0208等等,字符集简直是一个大乱斗。
Unicode是一个包含所有主要当前在用字符的新的标准,它包括了欧洲,亚洲,印度等等各种语言,Unicode的好处是它是可扩展的。到5.2版本,一共有超过 107000个字符。
Unicode编码点是兼容ISO8859的,也就是说它的前256个编码点就是ISO 8859-1.
要在计算机系统表示一个Unicode字符,需要使用一种编码方式。UCS(通用编码方式)使用两个字节进行编码,然而随着Unicod囊括的字符越来越多,UCS不再使用,而是使用 UTF-*的编码。UTF即 Unicode Transformation format.常见的编码方式如下:
- UTF-32 试用4字节编码,不常用,尤其是 HTML5 规范明确反对使用它
- UTF-16 将最常用的字符编码到2字节,应该也不常用
- UTF-8 一个字符使用1-4字节,不定长度,最常用的,对英文字符基本和ISO-8859对应,中文编码为3字符,相比GBK多一个字节
- UTF-7 有时使用,但不常用
要理解Unicode和UTF-8之间的区别和联系。知道UTF的名字是Unicode转换格式就可以了。Unicode是一个字符集,UTF-8是这个字符集的一种编码方式。
Go与字符集
UTF-8
UTF-8 是当前最常用的字符编码,据Google统计50%的网页使用UTF-8编码。我们知道UTF-8的发明者就是Go的作者,也就是Unix的作者Ken。Go使用UTF-8编码的字符组成其字符串。Go的字符串的每一个字符称为一个 rune
,它是 int32
的别名,因为一个Unicode字符的长度可能是1,2,3,4个字节,如果要统计字符数,就需要计算的是rune的个数而不是字节数了。字符数和字节数只有在是字符串只由ASCII字符组成时才是一样的。
下面是一个中文字符串的示例,它表示出Go中字符串中不同字符占用长度不一样。
str := "百度一下,你就知道" |
Go默认就是utf-8编码,所以如果你的项目要使用UTF-8的话,不需要做额外的字符集处理就可以了。