小白学习go基础篇3 -- map哈希表

本文详述Go语言中map的实现原理,包括数据结构、初始化、访问与写入、扩容及删除操作。同时探讨了map的非协程安全特性,并解析了sync.map的线程安全实现及其适用场景。
摘要由CSDN通过智能技术生成


前言

本文主要记录:
1.map的实现原理。
2.拉链法原理。
3.map是否协程安全的。
4.sync.map的实现原理。


一、map的实现原理

1.数据结构:

go中的map是同时使用了多个数据结构结合哈希表来实现的。go使用runtime.hmap这个struct来表示map

type hmap struct {
   
	// 存储的元素的个数
	count     int
	flags     uint8
	// 当前哈希表拥有的桶的数量
	B         uint8
	noverflow uint16
	// hash时用到的值
	hash0     uint32
	// []bmap 桶数组
	buckets    unsafe.Pointer
	oldbuckets unsafe.Pointer
	nevacuate  uintptr

	extra *mapextra
}

type mapextra struct {
   
	overflow    *[]*bmap
	oldoverflow *[]*bmap
	nextOverflow *bmap
}

// bmap实际上是一个可以存8个元素的uint8数组,存储的是 高8位的hash值
type bmap struct {
   
	tophash [bucketCnt]uint8
}
// 这里展示了更多的bmap数据结构的字段
type bmap struct {
   
    topbits  [8]uint8
    keys     [8]keytype 
    values   [8]valuetype
    pad      uintptr
    overflow uintptr
}

在这里插入图片描述

2.初始化:

map的初始化分为字面量(编译器)和运行期初始化两种方式。

2.1 字面量初始化方式:
1)当使用字面量进行初始化的key value键值对的个数小于25个时,底层实际上会一次性将所有的键值对都加进hashmap中。如下代码所示:

hash := make(map[string]int, 3)
hash["1"] = 2
hash["3"] = 4
hash["5"] = 6
  1. 当元素大于25个时,底层会使用两个切片,一个key的切片,一个value的切片,然后通过循环下标的方式对hash进行赋值操作。()
hash := make(map[string]int, 26)
vstatk := []string{
   "1", "2", "3", ..."26"}
vstatv := []int{
   1, 2, 3, ... , 26}
for i := 0; i < len(vstatk); i++ {
   
    hash[vstatk[i]] = vstatv[i]
}

2.2 运行时创建map的方式:
当创建的map容量比较小的时候,例如小于bucketSize 8 时,会在栈上创建,并且golang底层会使用如下的方式快速创建:

var h *hmap
var h1 hmap
var bv bmap
// 直接赋值初始化一个 hmap
h = &h1
b := &bv
// 初始化一个bmap
h.buckets = b
// 获得一个hash种子
h.hash0 = fashtrand0()

2.

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值