• 【golang笔记】字符串


    GO中的字符串

    字符的历史

    1个比特可以是0,也可以是1
    8个比特组成了1个字节
    全部为0时,代表数字0
    全部为1时,代表数字255
    1个字节能代表256个数字,两个字节能代表65536个数字
    更多的自己可以有更多的组合,更多的字节可以代表更多的范围,
    整数可以这样表示,那么字母呢。一堆0和1怎么也算不出字母A吧
    这里就需要用到编码了,我们可以用

    A->映射数字65->再映射成0100 0001

    要存储字符时就,就存储这个数字,要读取时,就通过映射关系找到这个字符。

    像这样通过收录许多字符然后给他们一一编号,得到一个字符编号对照表。这就是字符集。
    ASCII只收录了128个字母,其扩展字符集也就只有256个。后面通用字符集就出来了 Unicode 1990年开始研发,1994年正式发布。
    那汉字怎么办呢,所以出现了GB2312,没有繁体字也不行,BIG5,但是还有。。。这就促成了字符和二进制的合作。但是有了字符集就万事大吉了吗?那怎么存储这个内容呢“eggo世界”
    1个直接的办法就是转换成二进制,如果使用unicode字符集,拿到编号直接组合。就会拿到一大串二进制数位。问题出现了

    你怎么知道字符串内容要这样划分,也可以这样划分啊

    所以直接编号的方式是不可行的。那能不能直接定义一个长度,统一按照一种长度来保存,位数不足,高位补0。答案是可以的,这就是定长编码。但是就会造成大量空间的浪费,比如e用00000000 00000000 00000000 0110010132位来表示,就会有很多的无效位。
    定长编码不行,就用变长编码。来看一种解决方案。小编好用少字节,大编号用多字节。

    但是怎么划分字符边界呢?
    第一种,编号0-127 使用0xxxxxxxx来表示,x可以去0和1,开头的0作为固定标识位
    第二种,如果是128-2047 那么使用110xxxxx 10xxxxxx这种方式来表示 110和10作为固定标识位。
    第三种,2048-65525 同样的使用1110xxxx 10xxxxxx 10xxxxxx三个字节来表示
    来举个例子
    0110 0101 0开头说明是1个字节,转换成数字就是101 再通过字符集映射就是"e"
    11100100 10111000 10010110,1110开头说明是3个字节,我们转换成十进制数字就是19990,就是汉字“世”
    然后字符要怎么变成二进制呢。
    同样的世界的“界”,我们找到Unicode字符集中的十进制表示是30028,符合第三种情况,于是我们映射成1110xxxx 10xxxxxx 10xxxxxx,然后把编号转换成二进制01110101 01001100填入模板中。

    理解GO的字符串实现

    上述编码方式其实就是GO中默认的UTF8编码。
    现在我们已经知道了字符串要怎么存了,需要用字符集配合编码才可以。
    接下来我们看看字符串变量是什么结构。
    首先我们需要起始地址,这样我们才知道数据存在内存哪里。

    c语言说我们再内容结尾的地方放一个特定标识不就好了。C语言用的是编号为0的字符,但这就限定了我们不能再出现这个标识符了,否则就会出现不可预估的后果,所以GO没有采用这种方式,而是在地址数据的后面再添加一个长度字符,这个长度并不是字符个数(字符长度不定),而是字节数(字节是固定8位)。

    这样既可以找得到起始地址,也可以知道字符串长度,也不限制内容。
    OKgo语言中的字符串变量就是以这种形式保存的。另外注意。我们可以读取字符串中的内容,但是不允许通过str[i]='o'这种形式修改字符串。
    一部分原因是GO语言认为字符串内容是不会修改的,所以编译器会把这种形式的字符串分配到只读内存中。内存中,这些读,写,执行等权限为了保护程序的政策运行,但是也限制了我们不能修改只读的内容。另外字符串变量是可以共用底层字符串内容的。

    如果我们修改了s1的内容,那么s2所打印的内容也会被修改,这样的影响是不可预测的。如果非要修改,可以直接给整体变量赋新值,它存储的地址就会改变,并不会影响原来的数组。也可以把变量强制转换成slice

    这样会为slice变量重新分配新的内存,并且会拷贝原来字符串的内容,同样可以脱离只读内存的限制。

    参考:

    1. 幼麟实验室,https://www.bilibili.com/video/BV1hv411x7we?p=1
  • 相关阅读:
    面向对象三大特征之多态——Java笔记(七)
    面向对象三大特征之继承(extends)——Java笔记(六)
    this、访问修饰符——Java笔记(五)
    面向对象三大特征之封装与static——(Java学习笔记四)
    初识Java——(Java学习笔记一)
    HTTP/3 简介
    iis 500.19错误解决过程记录
    排序陷阱 List.Sort Linq.OrderBy
    锁的封装 读写锁、lock
    时间“Thu Aug 14 2014 14:28:06 GMT+0800”的转换
  • 原文地址:https://www.cnblogs.com/zhoujiayong/p/16136285.html
Copyright © 2020-2023  润新知