Golang中的map实现

总所周知,大多数语言中,字典的底层是哈希表,而且其算法也是十分清晰的。无论采用链表法还是开放寻址法,我们都能实现一个简单的哈希表结构。对于Go来说,它是具体如何实现哈希表的呢?以及,采取了哪些优化策略呢? 内存模型 map在内存的总体结构如下图所示。 头部结构体hmap type hmap struct { count int // 键值对个数 flags uint8 B uint8 // 2^B = 桶数量 noverflow uint16 // 溢出桶的个数 hash0 uint32 // hash seed buckets unsafe.Pointer // 哈希桶 oldbuckets unsafe.Pointer // 原哈希桶,扩容时为非空 nevacuate uintptr // 扩容进度,地址小于它的桶已被迁移了 extra *mapextra // optional fields } hmap即为map编译后的内存表示,这里需要注意的有两点。 B的值是根据负载因子(LoadFactor)以及存储的键值对数量,在创建或扩容时动态改变 buckets是一个指针,它指向一个bmap结构 桶结构体bmap type bmap struct { // tophash数组可以看做键值对的索引 tophash [bucketCnt]uint8 // 实际上编译器会动态添加下述属性 // keys [8]keytype // values [8]valuetype // padding uinptr // overflow uinptr } 虽然bmap结构体中只有一个tophash数组,但实际上,其后跟着8个key的槽位、8个value的槽位、padding以及一个overflow指针。如下图所示...

二月 1, 2020 · 2 分钟 · wmingj

用Golang实现并理解Web中间件

在编写web应用中,我们常常会遇到这样的需求,比如,我们需要上报每个API的运行时间到运维监控系统。这时候你可以像下述代码一样将统计的逻辑写到每个路由函数中。 ...

十二月 20, 2019 · 1 分钟 · wmingj

Golang中的string实现

说到string类型,我们往往都能很熟练地对它进行各种处理,包括迭代、随机访问和匹配等等操作。然而在工作中,我发现迭代一个字符串产生的字符的类型与随机访问一个字符的类型却并不相同,为什么会这么奇怪呢?于是我决定一探究竟 ...

十二月 11, 2019 · 1 分钟 · wmingj