Golang学习——string和slice切片
- string
- 整数存储
- 字符存储
- Unicode
- 存储
- 变长编码规则
- 字符串类型变量的结构
- 字符串变量的修改方式
- slice
- 通过make的方式定义变量
- new
- 底层数组
- slice扩容规则
- 1.预估扩容后的容量newCap
- 2.newCap个元素需多大内存
- 3.匹配到合适的内存规格
- 练习
string
整数存储
- 1个字节可以表示256个数字,2个字节可以表示65536个数字
字符存储
- 字符集:字符编号对照表。收录很多数字,给它们一一编号。
- 字符集的更迭
- 全球化统一标准——通用字符集
Unicode
- 于1990年开始研发并于1994年正式公布,实现了跨语言跨平台的文本转换与处理。
- 字符集促成了字符与二进制的合作。但不是万事大吉:如何存储?
存储
- 存储的歧义
- 字符边界解决:定长编码,位数不够高位补零。
- 缺点:浪费内存。
变长编码规则
- 解码的过程
- 编码的过程
- UTF-8是GO语言默认的编码方式:字符集配合编码
字符串类型变量的结构
- 变量:起始地址。在内容结尾处放特定标识符。
- c语言使用字符编号为0的字符。(字符串内容不能出现这个标识符)
- GO语言并没有采取相同方式,而是在起始地址后面多存一个长度,长度为字节个数。
- 可读取不能修改
- 原因:Go语言认为字符串内容是不会被修改的。会将定义的字符串内容分配到只读内存段。内存中的读、写、执行权限是为了保护程序正常运行。
- 字符串变量是可以共用底层字符串内容的。
字符串变量的修改方式
- 1.可以直接给变量整体赋新值,它存储的地址就会指向新的内容,并没有去“修改”原来的内存。
- 2.也可以把变量强制类型转换成字节slice,
- 这样会为slice变量重新分配一段内存,并且会拷贝原来字符串的内容,同样可以脱离只读内存的限制。
slice
- 元素存哪里,存了多少个元素,可以存多少个元素。
- 声明一个整型slice,变量ints由这样三个部分组成。
- slice的元素要存在一段连续的内存中
- data就是这个底层数组的起始地址,但因只分配了切片结构,所以为nil。
- 存储元素个数为0,容量也为0。
通过make的方式定义变量
- 不仅会分配这三部分结构,还会开辟一段内存作为它的底层数组。
- make会为ints开辟一端容纳5个整型元素的内存,还会把它们初始化为整型的默认值0,但是目前这个slice只存储了两个元素。
new
- new一个slice变量,同样会分配三部分结构,但它不负责底层数组的分配。data=nil。
- new的返回值就是slice结构的起始地址。
- 此时,这样的slice变量还没有底层数组。
- append用来分配底层数组。
- 通过append的方式添加元素,它就会给slice开辟底层数组。
底层数组
- 数组:同种类型的元素一个挨一个的存储。
- int型slice
- string型slice
- 是什么,底层就是什么数组。
- 不一定指向数组开头。
- 数组容量声明了就不能改变
- s1:1,2,3,左闭右开,从1开始,容量为9;
- s2:7,8,9,容量也为3;
- 索引左边决定容量,右边决定长度。
- 给s1扩大访问元素
- 给s2添加元素(copy,注意容量到2倍)
slice扩容规则
1.预估扩容后的容量newCap
- 非固定1.25
2.newCap个元素需多大内存
- NO
- 在许多编程语言中,申请分配内存,并不是直接与操作系统交涉,而是和语言自身实现的内存管理模块,它会提前向操作系统申请一批内存,分成常用的规格管理起来。待申请内存时,会帮助我们匹配到足够大且最接近的规格。
3.匹配到合适的内存规格
- 5*8=40,实际:匹配到48字节。
- 48/8=6个
练习
- 16 bytes=8 bytes(指针8个字节)+8 bytes(len,Go中64位机器下Int占8个字节)
- 多出来的是字节长度占的内存