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

401 阅读2分钟

本文已参与「新人创作礼」活动, 一起开启掘金创作之路。

参考:大佬文章

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

代码层原因

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

image.png

结果:

 因此每次重新 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值判断。参考文章~