Go语言实战之映射的内部实现和基础功能
你要爱就要像一个痴情的恋人那样去爱,像一个忘死的梦者那样去爱,视他人之疑目如盏盏鬼火,大胆去走你的夜路。——史铁生《病隙碎笔》
写在前面
- 嗯,学习
GO
,所以有了这篇文章 - 博文内容为
《GO语言实战》
读书笔记之一 - 主要涉及映射相关知识
你要爱就要像一个痴情的恋人那样去爱,像一个忘死的梦者那样去爱,视他人之疑目如盏盏鬼火,大胆去走你的夜路。——史铁生《病隙碎笔》
映射的内部实现和基础功能
映射
是一种数据结构
,是用于存储一系列无序
的键值对
。类比Java里的Map
,Python里的字典
,可以理解为以哈希值
做索引
,期望索引
可以在一定的连续内存范围内的类似数组的数据结构
。
映射
里基于键来存储值
。映射功能强大的地方是,能够基于键快速检索数据
。键就像索引一样,指向与该键关联的值。
内部实现
映射是一个集合
,可以使用类似处理数组和切片的方式迭代
映射中的元素。但映射是无序的集合
,无序的原因是映射的实现使用了散列表
.
映射的散列表
包含一组桶
。
在存储、删除或者查找键值对的时候,所有操作都要先选择一个桶
。把操作映射时指定的键
传给映射的散列函数
,就能选中对应的桶
。
这个散列函数
的目的是生成一个索引
,这个索引
最终将键值对
分布到所有可用的桶
里。对 Go 语言的映射来说,生成的散列键的一部分,具体来说是低位(LOB)
,被用来选择桶
。
桶的内部实现。映射
使用两个数据结构来存储数据,
- 第一个是
数组
,内部存储用于选择桶
的散列键
的高八位值
。用于区分每个键值对要存在桶里的那一项。 - 第二个是
字节数组
,用于存储键值对
。该字节数组先依次存储
了这个桶里所有的键
,之后依次存储
了这个桶里所有的值
。实现这种键值对的存储方式目的在于减少每个桶所需的内存。
映射存储的增加,索引分布越均匀,访问键值对的速度就越快,随着映射存储的增加,索引分布越均匀,访问键值对的速度就越快
。映射通过合理数量的桶来平衡键值对的分布
创建和初始化
Go 语言中有很多种方法可以创建并初始化映射,可以使用内置的make 函数
,也可以使用映射字面量
。
1 | package main |
创建映射时,更常用的方法是使用映射字面量
。映射的初始长度会根据初始化时指定的键值对的数量来确定。
映射的键可以是任何值
。这个值的类型可以是内置的类型
,也可以是结构类型
,只要这个值可以使用==
运算符做比较
切片、函数以及包含切片
的结构类型
由于具有引用语义,不能作为映射的键
,使用这些类型会造成编译错误
1 | package main |
- 声明一个存储字符串切片的映射
1 | // 创建一个映射,使用字符串切片作为值 |
使用映射
键值对赋值给映射,是通过指定适当类型的键并给这个键赋一个值来完成的
- 为映射赋值
1 | // 创建一个空映射,用来存储颜色以及颜色对应的十六进制代码 |
- 可以通过声明一个未初始化的映射来创建一个值为
nil
的映射,不能用于存储键值对.
1 | // 通过声明映射创建一个 nil 映射 |
从映射取值
时有两个选择:
第一个选择是,可以同时获得值,以及一个表示这个键是否存在的标志,
- 从映射获取值并判断键是否存在
1 | // 获取键 Blue 对应的值 |
另一个选择是,只返回键对应的值,然后通过判断这个值是不是零值来确定键是否存在
- 从映射获取值,并通过该值判断键是否存在
1 | // 获取键 Blue 对应的值 |
在Go
语言里,通过键来索引映射时,即便这个键不存在也总会返回一个值
。在这种情况下,返回的是该值对应的类型的零值
迭代映射
里的所有值和迭代数组或切片一样,使用关键字 range
- 使用
range
迭代映射
1 | // 创建一个映射,存储颜色以及颜色对应的十六进制代码 |
想把一个键值对从映射里删除,就使用内置的delete 函数
- 从映射中删除一项
1 | // 删除键为 Coral 的键值对 |
在函数间传递映射
在函数间传递映射并不会制造出该映射的一个副本
。实际上,当传递映射给一个函数,并对这个映射做了修改时,所有对这个映射的引用都会察觉
到这个修改,这个特性和切片类似,保证可以用很小的成本来复制映射
1 | package main |
1 | [Running] go run "d:\GolandProjects\code-master\demo\hello.go" |
映射的增长没有容量或者任何限制。同时内置函数 len
可以用来获取切片
或者映射
的长度
。但是内置函数 cap
只能用于切片
。
博文部分内容参考
© 文中涉及参考链接内容版权归原作者所有,如有侵权请告知,这是一个开源项目,如果你认可它,不要吝啬星星哦 :)
《GO语言实战》
© 2018-2023 liruilonger@gmail.com, All rights reserved. 保持署名-非商用-相同方式共享(CC BY-NC-SA 4.0)
Go语言实战之映射的内部实现和基础功能
https://liruilongs.github.io/2022/03/10/Go/Go语言实战之映射的内部实现和基础功能/