在大多数编程语言中,字符串是可以直接通过下标访问的,但是在使用 go 语言的时候,直接使用下标访问有时候会出现一些乱码。
<!--more-->
数组
在解决这个问题之前,要先了解一个东西--数组:数组是用于存储多个相同类型数据的集合。并且数组在申请内存的时候,是一次申请一块连续的内存。比如我们创建一个数组,里面存了这几个元素。
由于内存是连续的,元素的类型也是相同的,所以每个元素占用的内存空间也是固定的,比如 java 中 char 类型占用两个字节。数组的内存空间是平等划分的,这样就可以解释为什么可以靠下标访问了。
在可以用下标访问的语言中,字符串都是按照字符编码的。也就是说,你将字符串 “abcd” 赋给变量 a,本质上是创建了一个字符数组用来存放字符串。但是在 go 语言里不一样,go 语言的字符型是按照字节编码的,什么意思呢? 26 个英文字母,每个英文字母占一个字节,在 go 语言的 string 里面就占用一个字节。中文日文韩文就不一样了, go 语言内建只支持 utf8 编码,在 utf8 里面,有一部分汉字占用 3 个字节,一部分汉字占用 4 个字节。比如 "巧" 这个字,打印一下它的长度,发现这个 string 占用 3 个字节,加上 "a" 之后占用 4 个字节,应该能理解按字节编码的意思了。
编码
为什么要 go 要选择按照字节来编码呢,这其实是为了节省空间。想象一下,在UTF-8编码中,中文有些要三个字节,有一些要占用四个字节,而英文字母只需要占用一个字节。一个中文算一个字符,一个英文字母也算一个字符,但是占用的内存相差很大,假设有一个超长字符串,里面有英文字符远多于中文字符,如果按字符来存储,每个字符要分配四个字节。因为低于四个字节,有可能有些中文就不能正常存储了,在这种情况下,每存储一个英文字母,就要浪费三个字节的内存空间。
底层实现和其它语言就不一样,不同类型的字符占用的内存空间都不同,当然也就没有办法按照下标访问了,不信可以试试。
a[0] 是 97,等于字母 a 的 ascii 码,a[1] 是 229,显然不会是汉字 "巧" 的 utf8,事实它是 utf8 编码的第一字节的值。
打完收工,到这里弄清楚了 go 中 string 不能按照下标访问的原理了
公众号:没有梦想的阿巧 后台回复 "群聊",一起学习,一起进步
有疑问加站长微信联系(非本文作者)