go语言map个数 go语言map扩容( 三 )


扩容时map并不会立即把新数据做迁移,而是当访问原来旧bucket的数据的时候,才把旧数据做迁移,如下图:
注意:这里并不会直接删除旧的bucket,而是把原来的引用去掉,利用GC清除内存 。
map中数据的删除
如果理解了map的整体结构,那么查找、更新、删除的基本步骤应该都很清楚了 。这里不再赘述 。
值得注意的是,找到了map中的数据之后,针对key和value分别做如下操作:
1
2
3
4
1、如果``key``是一个指针类型的,则直接将其置为空,等待GC清除go语言map个数;
2、如果是值类型的,则清除相关内存 。
3、同理 , 对``value``做相同的操作 。
4、最后把key对应的高位值对应的数组index置为空 。
Go语言——sync.Map详解 sync.Map是1.9才推荐的并发安全的map , 除了互斥量以外,还运用了原子操作,所以在这之前 , 有必要了解下 Go语言——原子操作
go1.10\src\sync\map.go
entry分为三种情况:
从read中读取key,如果key存在就tryStore 。
注意这里开始需要加锁 , 因为需要操作dirty 。
条目在read中 , 首先取消标记,然后将条目保存到dirty里 。(因为标记的数据不在dirty里)
最后原子保存value到条目里面,这里注意read和dirty都有条目 。
总结一下Store:
这里可以看到dirty保存了数据的修改,除非可以直接原子更新read,继续保持read clean 。
有了之前的经验 , 可以猜测下load流程:
与猜测的 区别 :
由于数据保存两份,所以删除考虑:
先看第二种情况 。加锁直接删除dirty数据 。思考下貌似没什么问题 , 本身就是脏数据 。
第一种和第三种情况唯一的区别就是条目是否被标记 。标记代表删除,所以直接返回 。否则CAS操作置为nil 。这里总感觉少点什么 , 因为条目其实还是存在的,虽然指针nil 。
看了一圈貌似没找到标记的逻辑,因为删除只是将他变成nil 。
之前以为这个逻辑就是简单的将为标记的条目拷贝给dirty,现在看来大有文章 。
p == nil,说明条目已经被delete了,CAS将他置为标记删除 。然后这个条目就不会保存在dirty里面 。
这里其实就跟miss逻辑串起来了,因为miss达到阈值之后,dirty会全量变成read,也就是说标记删除在这一步最终删除 。这个还是很巧妙的 。
真正的删除逻辑:
很绕 。。。。
go语言怎样处理 map 的值// 先声明map
var m1 map[string]string
// 再使用make函数创建一个非nil的map,nil map不能赋值
m1 = make(map[string]string)
// 最后给已声明的map赋值
m1["a"] = "aa"
m1["b"] = "bb"
// 直接创建
m2 := make(map[string]string)
// 然后赋值
m2["a"] = "aa"
m2["b"] = "bb"
// 初始化 + 赋值一体化
m3 := map[string]string{
"a": "aa",
"b": "bb",
}
望采纳 。。
// ==========================================
// 查找键值是否存在
if v, ok := m1["a"]; ok {
fmt.Println(v)
} else {
fmt.Println("Key Not Found")
}
// 遍历map
for k, v := range m1 {
fmt.Println(k, v)
}
go语言map个数的介绍就聊到这里吧 , 感谢你花时间阅读本站内容,更多关于go语言map扩容、go语言map个数的信息别忘了在本站进行查找喔 。

推荐阅读