当前位置: 首页 > news >正文

golang面经3——map模块和sync.Map模块

一、面试题相关

1、map的数据结构详解

        map就是一个hmap的结构。Go Map的底层实现是一个哈希表。它在运行时表现为一个指向 hmap 结构体的指针,hmap中记录了桶数组指针buckets溢出桶指针以及元素个数等字段。每个桶是一个bmap结构体,能存储8个键值对和8个 tophash,并有指向下一个溢出桶的指针 overflow。为了内存紧凑,bmap 中采用的是先存8个键再存8个值的存储方式。

        1)hmap结构(Map的头部)

type hmap struct { count int // 当前存储的键值对数量 flags uint8 // 状态标志(如是否正在写入) B uint8 // B=5的话,桶的数量就是32个。桶数量的对数(桶数量 = 2^B) noverflow uint16 // 溢出桶的大概数量 hash0 uint32 // 哈希种子(用于防御Hash-DoS攻击) buckets unsafe.Pointer // 指向桶数组的指针 oldbuckets unsafe.Pointer // 扩容时指向旧桶数组 nevacuate uintptr // 搬迁进度计数器 extra *mapextra // 可选字段,用于优化小对象存储 }

2)bmap结构(桶结构)

// 这是一个概念上的结构,并非源码中的实际定义 type bmap struct { // 1. 顶部哈希数组 (固定8个元素) tophash [bucketCnt]uint8 // bucketCnt 常量,值为 8 // 2. 接下来是 8 个键 (key) // keys [bucketCnt]keyType // keyType 在编译时确定 (例如 int, string 等) // 3. 再接下来是 8 个值 (value) // values [bucketCnt]valueType // valueType 在编译时确定 // 4. 最后是一个溢出桶指针 (可选,在特定条件下才存在) // overflow *bmap }

        每个桶可以存储最多8个键值对:

tophash的作用

        tophash [bucketCnt]uint8 // bucketCnt 常量,值为 8
        uint是一个字节8位(0~255),存储每个键哈希值的高8位
        用于快速比较,避免直接比较可能很大的key。利用tophash只是进行初步的过滤,将指定key高8位相同的key从bucket里找到,然后再从找到的key中进行完整的对比确认找的是哪个key。
        特殊值:

                0=空槽位(emptyRest):该槽位为空,且后面所有槽位都为空

                1=已删除槽位(emptyOne):仅该槽位为空,后面可能有非空槽位

溢出桶机制
        当单个桶存储超过8个元素时,会创建溢出桶:

                主桶 → 溢出桶1 → 溢出桶2 → ...


        每个溢出桶也是bmap结构,可以继续存储8个元素。

2.map中新加入一个新的成员得流程

(1)计算哈希值:根据 key 计算出一个哈希值。
(2)定位桶:利用哈希值的低位确定 key 应该存放在哪个桶中。
(3)遍历桶:依次检查桶内的每个槽位(也称为 cell)。
(4)查找或插入:
        情况一(Key 已存在):如果找到相同的 key,则更新其对应的 value。
        情况二(Key 不存在):如果 key 不存在,则寻找一个空槽位进行插入。
(5)处理溢出:如果当前桶已满,则需要链接一个新的溢出桶。
(6)扩容检查:在插入后,可能会触发 map 的扩容机制。

通过key hash值的低8位(当B为3的时候,如果B为4,就取低16位)确定使用哪个桶

通过key hash值的高8位存到桶内的tophash中

3.map 循环遍历是有序的还是无序的?

分析:

        考察对map遍历的底层实现是否了解,map在每次遍历的时候都会选定一个随机桶号,遍历从这个随机桶开始往后依次遍历完所有的桶,在每个桶内,则是按照之前选定随机槽位开始遍历,回答的时候要突出随机桶号和随机槽位。

回答:

        map的遍历是无序的,map每次遍历,都会从一个随机值序号的桶,在每个桶中,再从按照之前选定随机槽位开始遍历,所以是无序的。

4.go语言的map要这样设计,要随机选定桶号和槽位进行随机遍历?

分析:

        因为map是可以动态扩容的,map 在扩容后,会发生 key 的搬迁,这样 key 的位置就会发生改变,那么如果顺序谝历key,在扩容前后顺序肯定会不一样,这道题回答一定要突出扩容会带来key的位置发生变化回顾一下双倍扩容,key的变化过程,双倍扩容,目标桶扩容后的位置可能在原位置也可能在原位置+偏移量处。

回答:

        因为map 在扩容后,会发生 key 的搬迁,原来落在同一个 bucket 中的 key,搬迁后,有些 key 的位置就会发生改变。而遍历的过程,就是按顺序遍历 b

http://www.jsqmd.com/news/1275696/

相关文章:

  • DCSCN-Super-Resolution实战:用预训练模型提升你的图片分辨率
  • 探索智能体开发新边界:Cangjie Magic开源平台体验与解析
  • 有哪些真实可靠、正规的求职招聘平台推荐 赶集招聘使用评测 - 资讯纵览
  • Spring-AI 接入(本地大模型 deepseek + 阿里云百炼 + 硅基流动)
  • AI Agent 泡沫复盘:从 “养龙虾” 热潮看技术落地的底层逻辑
  • 石家庄闲置黄金变现渠道?收的顶各区分店整理,全天候专线 4008676661 - 一日一测评
  • 2026 年现阶段,余姚热门的源头 414405 H 型钢源头厂销售厂家综合实力解析,别再花冤枉钱!414x405 H型钢的秘密源头揭秘-中拓兴耀无缝钢管 - 企业信息推荐【官方】
  • TI FPD-Link III SerDes评估板实战:DS90UB927QEVM硬件设计与信号调试指南
  • BGE-M3联合嵌入在FastEmbed-rs中的应用: dense、sparse与ColBERT三合一
  • 数字电源保护功能深度解析:UV/OC/OT保护配置与工程实践
  • 2026年成都高考复读学校综合实力榜单:选校指南与招生信息盘点 - 资讯报道
  • 如何定制Ventoy启动菜单:打造个性化系统安装体验
  • 霞鹜文楷:如何为你的设备免费安装这款优雅的开源中文字体
  • 芯片封装选型实战:从WQFN到csBGA,如何为LM8333运放选择最佳封装
  • 深圳学生配眼镜别大意!选对青控镜片是关键 - 配眼镜新资讯
  • 从 curl 到工程封装:构建全网热搜数据聚合层
  • 3天构建可转债套利监控系统:量化交易实战指南
  • 终极原神抽卡分析工具:免费快速导出你的祈愿历史完整指南
  • 终极指南:如何轻松使用VIA桌面版打造个性化机械键盘
  • 为什么选择MVPArmsTemplate?Android开发者不可错过的架构利器
  • Oracle:参数化“常量”
  • 2026 有实力的AI外贸获客系统解决方案商场景攻略 - 信息热点
  • 2026成都复读学校招生季:12所合规学校办学资质与提分效果一览 - 资讯报道
  • recon-skills高级技巧:8种CORS漏洞变体与防御绕过实战案例
  • 技术深度解析:palera1n越狱工具的核心原理与高级配置指南
  • 2027亚洲消费电子展62%专业观众手握核心决策权
  • 10分钟上手Zend-Expressive:构建你的第一个中间件应用
  • 【JAVA毕业设计】基于 Java 的高校网络运维综合管理系统校园网络资源管理与故障处理平台 (源码+文档+远程调试,全bao定制等)
  • SDR++终极指南:如何用这款免费开源软件定义无线电工具改变你的频谱监测体验
  • 解锁游戏边界:用Sunshine打造你的跨设备游戏空间