go语言map的实现 go语言map底层实现原理

面试问题总结(一)Golang 使用go语言的好处: go语言的设计是务实的, go在针对并发上进行了优化, 并且支持大规模高并发, 又由于单一的码格式, 相比于其他语言更具有可读性, 在垃圾回收上比java和Python更有效, 因为他是和程序同时执行的.
1. 进程, 线程, 协程的区别, 协程的优势
2. 讲一下GMP模型(重点)
3. Go的GC, 混合写屏障(重点)
4. go的Slice和数组的区别, slice的扩容原理(重点)
5. 讲一下channel,实现原理(重点)
6. 讲一下Go的Map的实现原理, 是否线程安全, 如何实现安全(重点)
7. new 和 make 的区别
8. 说一下内存逃逸
9. 函数传指针和传值有什么区别
10. goroutine之间的通信方式
11. 测试是怎么做的(单元测试, 压力测试)
12. 堆和栈的区别
Golang中sync.Map的实现原理前面,我们讲了map的用法以及原理 Golang中map的实现原理 ,但我们知道,map在并发读写的情况下是不安全 。需要并发读写时,一般的做法是加锁,但这样性能并不高,Go语言在 1.9 版本中提供了一种效率较高的并发安全的 sync.Map,今天 , 我们就来讲讲 sync.Map的用法以及原理
sync.Map与map不同,不是以语言原生形态提供,而是在 sync 包下的特殊结构:
我们下来看下sync.Map结构体
结构体之间的关系如下图所示:
总结一下:
Load方法比较简单,总结一下:
总结如下:
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",
}
望采纳 。。
// ==========================================
// 查找键值是否存在
【go语言map的实现 go语言map底层实现原理】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 时尽量不要在 big map 中保存指针 不知道你有没有听过这么一句:在使用 map 时尽量不要在 big map 中保存指针 。好吧,你现在已经听过了:)为什么呢?原因在于 Go 语言的垃圾回收器会扫描标记 map 中的所有元素,GC 开销相当大,直接GG 。
这两天在《Mastering Go》中看到 GC 这一章节里面对比 map 和 slice 在垃圾回收中的效率对比,书中只给出结论没有说明理由 , 这我是不能忍的,于是有了这篇学习笔记 。扯那么多 , Show Your Code
这是一个简单的测试程序,保存字符串的 map 和 保存整形的 map GC 的效率相差几十倍,是不是有同学会说明明保存的是 string 哪有指针?这个要说到 Go 语言中 string 的底层实现了 , 源码在 src/runtime/string.go里,可以看到 string 其实包含一个指向数据的指针和一个长度字段 。注意这里的是否包含指针,包括底层的实现 。
Go 语言的 GC 会递归遍历并标记所有可触达的对象 , 标记完成之后将所有没有引用的对象进行清理 。扫描到指针就会往下接着寻找,一直到结束 。
Go 语言中 map 是基于 数组和链表 的数据结构实现的,通过 优化的拉链法 解决哈希冲突,每个 bucket 可以保存8对键值,在8个键值对数据后面有一个 overflow 指针 , 因为桶中最多只能装8个键值对,如果有多余的键值对落到了当前桶,那么就需要再构建一个桶(称为溢出桶),通过 overflow 指针链接起来 。

推荐阅读