本文转载自微信公众号《我的大脑是炸鱼》,作者陈建宇。转载本文请联系脑筋急转弯公众号。大家好,我是炸鱼。很多朋友在学习Go语言语法的时候,可能对这个问题只是看淡了。结果一上手,在群里或多或少都会遇到(我经常看到。。。)。甚至有一定年限的程序员也会被发现。有小伙伴疑惑为什么这么折腾Go不直接在语言层面支持map并发,想都没想就用了。那有多好吃?为什么它不被原生支持?为什么官方不支持Go?会不会太复杂,性能太差?为什么?官方回答如下(来自@gofaq):典型使用场景:map典型使用场景不需要多个goroutines的安全访问。非典型场景(需要原子操作):地图可能是一些更大的数据结构的一部分或已经同步的计算。性能场景考虑:如果只增加少数几个程序的安全性,导致所有map操作都处理mutex会降低大部分程序的性能。核心是:经过长时间的讨论,Go团队认为原生地图应该更适合典型的使用场景。如果是针对少数情况,会导致大部分程序付出性能代价,决定不支持原生并发map读写。并且从Go1.6开始,加入了检测机制,如果并发,就会引发异常。为什么会崩溃前面说了,从Go1.6开始,会进行nativemaps的并发检测,这对某些人来说是个“噩梦”。这里有人吐槽:“明明就是丢给我一个错误,为什么我的Go进程要直接崩溃,而且每分钟都要记一个P0”。场景枚举这里我们假设如果并发读写map是以下两种场景:Panic:程序panic->默认进入recover->不处理concurrentmap->map有脏数据->程序使用了脏数据->生成**unknown((impact.crash:程序崩溃->直接crash->保留数据(数据正常)->生成**clear((有风险。你会选择哪种解决方案?去官网我选择了第二种在笔者的风险评估中,无论是编程还是生活,如何掌握随机性的确定性部分,也是一大哲理。letitcrashGo官方团队选择的方法是业界经典的“letitcrash”行为,被许多编程语言作为设计理念采用。letitcrash意味着工程师不必过多担心未知错误,而是进行全面的防御性编码。这种思想最经典的是erlang。小结在今天的文章中,我们介绍了为什么Go语言不支持原生map并发。核心原因是大部分场景不需要,是从性能角度考虑的。之所以直接允许map并发读写,是考虑“让它崩溃”。如果想在自己的项目中避免这种情况,可以在linter等工具链中加入racedetection(-race),也可以规避这种风险。您如何看待Go中的设计考虑因素?
