20210209关于[]byte和[]rune(1) - ziyouzy/2021blog GitHub Wiki
[]rune和[]byte是同一类型的东西
而string是由[]byte封装而来的,string拥有着切片的特性,也就是底层数组的特性,因此和切片一样,要注意因共享底层数组所造成的销毁与生命周期的问题
这里有篇基础文章可以看看:
https://www.cnblogs.com/neozheng/p/13123542.html
现在重点探讨一下[]byte("你好 world")的问题:
一个byte可以分别储存"w","o","r","l","d",但是无法储存"wo"
同时虽然也是一个编码,但是一个byte无法储存一个中文的字符:"你",更不要提"你好"了
其实这个要从一切问题的起点说起,比如说现在我此时此刻用markdown在输入英文与中文,对这个输入框来说,“印上去”的内容的底层其实都是一个个16进制数
如{0x91,0x81,0x88,0x1F}这样的,本质上是golang的byte或c++的char,但是这个输入框(或vscode编译器)会通过utf8编码格式先进行一种类似间断的操作:
{{0x91,0x81,0x88,},{0x1F,0xFF,0x31,},{0x77,0x88,0x99},}
之后再直观的根据这些调用显示出对应的英文或中文
这种间断的实现其实是基于byte的容量所决定的,也就是int8的容量,也就是8位二进制数,8位二进制可以保存1个16进制数
值得注意的是这表面上看似乎可以呈现出一种显示规则,但是并不是,他只是某种显示规则的底层,如比uf8早期很多的ascii,是用7位或8位二进制数来表示a-z这些字符的,同时也包括“#¥%”这些
重点在于7位,从这里可以明确一点,ascii编码是基于(面向)2进制数的,而不是基于16进制数,更不是基于byte,char这些数据类型
也即是说上面的所谓的间断对于ascii来说是这样的:
{{0,0,0,1,0,0,1,},{1,1,1,0,0,1,1,},{0,1,0,1,0,1,0,},}
而UTF-8使用1~4字节为每个字符编码,也就是他首先是面向字节的,而字节是基于2进制数封装出的高级一些的数据类型
于是这直接决定了无论是哪种输入框(vscode,现在这个,或者说window记事本,或者ubuntu的gedit,ubuntu的命令行终端),起码都要先确认下用户想使用utf8还是ascii
输入的过程(也就是输入法之类的)不用考虑太多,需要考虑的是当文字“印在”输入框内部的时候,他的最低层依然是2进制数,连续的未进行上面所说“间断”二进制数
之后如果输入框是ascii则这些连续的二进制数就会先按照7位到8位去切割再进行之后的处理
这里需要注意的是ascii是借助什么工具(如char这种8位2进制数据类型,还是某种7位2进制的数据类型),暂时是不得而知,也不用考虑的
如果输入框是基于utf8则直接需要去切割[4]char(也可以理解成golang中的[4]byte)这种数据类型
无论如何大致上可以理解成,utf8与ascii存在着一种“底层原子级区别”,也就是utf8的底层是字节,ascii的底层是二进制数,字节与二进制差着一个级别