Go 语言核心 36 讲
郝林
《Go 并发编程实战》作者,前轻松筹大数据负责人
79610 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 55 讲
Go 语言核心 36 讲
15
15
1.0x
00:00/00:00
登录|注册

09 | 字典的操作和约束

把键值转换为哈希值
字典类型的值是否并发安全
写操作会引发panic
读操作不会引起错误
求哈希和判等操作速度快的类型
出现哈希碰撞时需要对比键值
不能是函数类型、字典类型和切片类型
映射过程
存储键-元素对
键值对的对应关系
代表一对键和值
存储键值对的集合
单一元素的容器
并发安全性
在值为nil的字典上执行读操作和写操作
优先考虑哪些类型作为字典的键类型
键类型的值必须支持判等操作
字典的键类型受到约束
哈希表
映射
键值对
字典(map)
集合类的高级数据类型
字典的操作和约束

该思维导图由 AI 生成,仅供参考

至今为止,我们讲过的集合类的高级数据类型都属于针对单一元素的容器。
它们或用连续存储,或用互存指针的方式收纳元素,这里的每个元素都代表了一个从属某一类型的独立值。
我们今天要讲的字典(map)却不同,它能存储的不是单一值的集合,而是键值对的集合。
什么是键值对?它是从英文 key-value pair 直译过来的一个词。顾名思义,一个键值对就代表了一对键和值。
注意,一个“键”和一个“值”分别代表了一个从属于某一类型的独立值,把它们两个捆绑在一起就是一个键值对了。
在 Go 语言规范中,应该是为了避免歧义,他们将键值对换了一种称呼,叫做:“键 - 元素对”。我们也沿用这个看起来更加清晰的词来讲解。

知识前导:为什么字典的键类型会受到约束?

Go 语言的字典类型其实是一个哈希表(hash table)的特定实现,在这个实现中,键和元素的最大不同在于,键的类型是受限的,而元素却可以是任意类型的。
如果要探究限制的原因,我们就先要了解哈希表中最重要的一个过程:映射。
你可以把键理解为元素的一个索引,我们可以在哈希表中通过键查找与它成对的那个元素。
键和元素的这种对应关系,在数学里就被称为“映射”,这也是“map”这个词的本意,哈希表的映射过程就存在于对键 - 元素对的增、删、改、查的操作之中。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入探讨了Go语言中字典类型的特性和使用限制。首先介绍了字典类型的特点,以及键类型受到约束的原因,重点讨论了在选择键类型时需要考虑的性能因素。文章指出,对于基本类型、指针类型以及宽度较小的类型,其哈希和判等操作速度较快,因此更适合作为字典的键类型。同时,对于高级数据类型如数组、结构体和接口类型,存在值的变化和性能较慢等问题,不建议作为键类型。此外,文章还解答了在值为`nil`的字典上执行读写操作的情况,强调了对可能引发panic的操作需要特别注意。最后,提出了关于字典类型值的并发安全性的思考题,引发读者对并发安全性的思考。通过本文的阅读,读者能够深入了解字典类型的特性和使用限制,以及在实际开发中需要注意的细节和问题。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Go 语言核心 36 讲》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(49)

  • 最新
  • 精选
  • 江山如画
    非原子操作需要加锁, map并发读写需要加锁,map操作不是并发安全的,判断一个操作是否是原子的可以使用 go run race 命令做数据的竞争检测

    作者回复: 说得很对

    2018-09-01
    3
    136
  • 张民
    郝大,有个疑问:文中描述“也就是说,字典不会存储任何键值,只会存储它们的哈希值。“ 但是在查找的时候,根据键值的哈希找到后,又去比较键值,防止哈希碰撞。但是键值没有存储怎么比较?

    作者回复: 哈希桶里的结构是,“键的哈希值-内部结构”对的集合,这个内部结构的结构是“键1元素1键2元素2键3元素3”,是一块连续的内存。在通过键的哈希值定位找到哈希桶和那个“键的哈希值-内部结构”对之后,就开始在这个内部结构里找有没有这个键。后边的事情你应该都知道了。

    2018-08-31
    4
    50
  • Geek_1ed70f
    不知道是理解能力差,还是基础差,以前只会随便用用,现在读您的文章,读完第一遍似懂非懂,然后用一下午时间翻源码,看解释,弄原理...再回头一读豁然开朗,.....精学了,但是好费时间啊,~~~~~老师如何评价进度与学习成本的取舍呢

    作者回复: 你这个时间成本是值得的。真正的学习没有捷径啊。

    2019-02-07
    8
  • 星云
    "也就是说,字典不会存储任何键值,只会存储它们的哈希值。" 我也觉得这个说法不严谨,既然,"内部结构"是将键值对捆绑存的,那字典就是存了键,除非"内部结构"不属于字典? 可能没理解到,请郝大指点迷津

    作者回复: 好吧,可以说,不会独立存储键的值。

    2018-09-04
    7
  • NIXUS
    nil的map,既然不能添加key-element,是否也就意味着这样的map是没有任何意义的?在使用中,应避免用`var m map[string]int` 这种方式来声明map呢?

    作者回复: 可以对m直接用索引表达式添加啊。

    2018-10-28
    3
    6
  • extraterrestrial!!
    函数类型为啥不能判等呢,函数头相同就认为相等不行么?

    作者回复: 这是Go语言的规定,没必要纠结,你完全用类型断言去判断啊。

    2018-09-04
    5
  • kuzan
    go里面有没有分段锁的字典实现呢

    作者回复: 没有,sync.Map也不是分段锁实现的,如果想看分段锁实现可以看我的《Go并发编程实战》第二版中的例子。

    2018-10-09
    4
  • 松小鼠
    结构体作为map的元素时,不能够直接赋值给结构体的某个字段,也就是map中的struct中的字段不能够直接寻址,请问为什么,该怎么处理?

    作者回复: 因为 map 内部的元素值的存储地址是会不定期自动变化的(因为会 rehash),所以不可寻址。这也是Go语言规范里说明的。 你不可以直接对 map 中的元素值取址,比如:&map1["a"] ,但是你可以先 var1 := map1["a"] 再 &var1 啊,或者索性把 map1 的元素类型设置成那个结构体的指针类型。 从编码层面是可以这么解决的。而从程序设计层面,你需要想想“你为什么要这么取址?”,以及“是不是哪里设计得不够好?”。

    2020-10-13
    3
  • colonel
    哈希桶怎么存储的,是数组吗?碰撞之后的键值又是怎么存储的,形成链表吗?删除机制中,是删除链表中节点吗? 建议,不要大篇幅讨论存储性能,可以对内部数据存储,插入,删除,读取机制更多分享

    作者回复: 这些文章里都有写。

    2018-09-22
    3
  • SuperP ❤ 飝
    一个哈希表会持有一定数量的桶(bucket),那个新增加一个键值得时候,怎么去划分桶的?

    作者回复: 我记得文章里讲了。

    2018-09-13
    3
收起评论
显示
设置
留言
49
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部