为什么遍历 Go map 是无序的?原生map为什么是非线程安全的?

简介: 为什么遍历 Go map 是无序的?原生map为什么是非线程安全的?

 参考:大佬文章

一、为什么遍历 Go map 是无序的?

代码层原因:

for range map 在开始处理循环逻辑的时候,就做了随机播种,用于决定从哪里开始循环迭代。更具体的话就是根据随机数,选择一个桶位置作为起始点进行遍历迭代。

image.gif编辑

结果:

因此每次重新 for range map,你见到的结果都是不一样的。那是因为它的起始位置根本就不固定!

根本原因:

你想问为什么要这么做?当然是官方有意为之,因为官方在 Go 早期的时候,发现很多工程师都较依赖 map 的遍历迭代顺序。但这将会导致可移植性存在问题。因此,改之。也请不要依赖...

二、go语言为什么不在语言层面保证map线程安全?

Golang1.9版本后,增加了并发安全的sync.Map。相比原生map加互斥锁的解决方案,性能稍微高一点。去读下代码,就知道这个东西虽然也用了锁,但还是做了一些优化。至于原生map为什么不是并发安全,这个很好理解。并发安全是有代价的。如果原生map保证并发安全,那么一些不需要并发的场景,会有不小的性能损耗

      一个常见的场景,比如你在函数内无并发需求,仅需要一个临时map存kv,也用加锁的map么? 嗯,开销有些大了。所以,原生map就单纯实现map基础就好了。要安全,加锁。(分并发场景来就行~)

三、map如何判断某个key在map中是否存在?

map通过hash值的高8位和低8位来快速判断key是否存在,并通过返回ok值判断。参考文章~

目录
相关文章
|
28天前
|
存储 安全 测试技术
【Go语言精进之路】构建高效Go程序:了解map实现原理并高效使用
【Go语言精进之路】构建高效Go程序:了解map实现原理并高效使用
32 3
|
20天前
|
Go
go语言map、实现set
go语言map、实现set
28 0
|
9天前
|
JavaScript API
js【最佳实践】遍历数组的八种方法(含数组遍历 API 的对比)for,forEach,for of,map,filter,reduce,every,some
js【最佳实践】遍历数组的八种方法(含数组遍历 API 的对比)for,forEach,for of,map,filter,reduce,every,some
21 1
|
24天前
|
缓存 安全 算法
Go 中使用 map 实现高效的数据缓存
Go 中使用 map 实现高效的数据缓存
|
24天前
|
存储 缓存 安全
Go 中使用 map 实现高效的数据查找和更新
Go 中使用 map 实现高效的数据查找和更新
|
21天前
|
缓存 Java 测试技术
探讨Java中遍历Map集合的最快方式
探讨Java中遍历Map集合的最快方式
15 1
|
3天前
|
安全 Go
Go语言map并发安全,互斥锁和读写锁谁更优?
Go并发编程中,`sync.Mutex`提供独占访问,适合读写操作均衡或写操作频繁的场景;`sync.RWMutex`允许多个读取者并行,适用于读多写少的情况。明智选择锁可提升程序性能和稳定性。示例展示了如何在操作map时使用这两种锁。
6 0
|
3天前
|
安全 Go 开发者
Go语言map并发安全使用的正确姿势
在Go并发编程中,由于普通map不是线程安全的,多goroutine访问可能导致数据竞态。为保证安全,可使用`sync.Mutex`封装map或使用从Go 1.9开始提供的`sync.Map`。前者通过加锁手动同步,后者内置并发控制,适用于多goroutine共享。选择哪种取决于具体场景和性能需求。
6 0
|
3天前
|
存储 安全 Java
Go语言中的map为什么默认不是并发安全的?
Go语言的map默认不保证并发安全,以优化性能和简洁性。官方建议在需要时使用`sync.Mutex`保证安全。从Go 1.6起,并发读写map会导致程序崩溃,鼓励开发者显式处理并发问题。这样做的哲学是让代码更清晰,并避免不必要的性能开销。
4 0
Map集合的有序遍历,解决方法多看一下别人的资料
Map集合的有序遍历,解决方法多看一下别人的资料