面试题:Go 1.15 中 var i interface「」 = 3
说明:题目是这样的
varinint=3//以下有额外内存分配吗?variinterface{}=i在Go中 , 接口被实现为一对指针(请参阅RussCox的Go数据结构:接口[1]):指向有关类型信息的指针和指向值的指针 。 可以简单的表示为:
typeifacestruct{tab*itabdataunsafe.Pointer}其中tab是指向类型信息的指针;data是指向值的指针 。 因此 , 一般来说接口意味着必须在堆中动态分配该值 。
然而 , Go1.15发行说明[2]在runtime部分中提到了一个有趣的改进:
Convertingasmallintegervalueintoaninterfacevaluenolongercausesallocation.
意思是说 , 将小整数转换为接口值不再需要进行内存分配 。 小整数是指0到255之间的数 。
我们实际简单测试一下 。
创建一个包smallint , 在包中创建文件smallint.go , 加上如下代码:
packagesmallintfuncConvert(valint)[]interface{}{varslice=make([]interface{},100)fori:=0;i为了更好的看到效果 , 函数中进行了100次int到interface的转换 。 写个基准测试smallint_test.go:
packagesmallint_testimport("testing""test/smallint")funcBenchmarkConvert(b*testing.B){fori:=0;i分别使用Go1.14和Go1.15版本进行测试:
$goversiongoversiongo1.14.7darwin/amd64$gotest-bench.-benchmem./...goos:darwingoarch:amd64pkg:test/smallintBenchmarkConvert-85698301966ns/op2592B/op101allocs/opPASSoktest/smallint1.647s$goversiongoversiongo1.15darwin/amd64$gotest-bench.-benchmem./...goos:darwingoarch:amd64pkg:test/smallintBenchmarkConvert-81859451655ns/op1792B/op1allocs/opPASSoktest/smallint2.178s接着讲smallint_test.go中调用Convert的参数由12改为256 , 再次使用Go1.15运行 , 结果如下:
$gotest-bench.-benchmem./...goos:darwingoarch:amd64pkg:test/smallintBenchmarkConvert-85515462049ns/op2592B/op101allocs/opPASSoktest/smallint1.502s证明了上面提到的优化点 。
那么 , 你想过它大概怎么实现的吗?因为上文提到 , Go中接口的实现 , 使用一个指针字段指向接口值 。 现在竟然不再额外进行内存分配 , 说明做了什么特殊的事情 。
其实答案非常简单 。 如果你对Python、Java等语言熟悉 , 应该知道大概如何实现的 。 Go中如何做的 , 可以在GoCL216401[3]中(合并到此提交[4]中了 , GitHub上更易于阅读)找到 。 具体来说就是Go中定义了一个特殊的静态数组 , 该数组由256个整数组成(0到255) 。 当必须分配内存以将整数存储在堆上 , 并将其转换为接口的一部分时 , 它首先检查是否它可以只返回指向数组中适当元素的指针 。 这种经常使用的值的静态分配 , 是一种很常见的优化手段 。 例如 , Python对小整数执行类似的操作 , Java也有常量池 , 进行类似的优化处理 。
实际上 , Go以前有一个优化 , 如果你将0转换为接口值 , 它将返回一个指向特殊静态零值的指针 。 这次新的0-255优化替代了该值 。
对具体实现细节感兴趣的 , 可以阅读下上文提到的提交 。
参考资料[1]
Go数据结构:接口:
[2]
Go1.15发行说明:
[3]
GoCL216401:+/216401
[4]
【面试题:Go 1.15 中 var i interface「」 = 3】此提交:
推荐阅读
- 科学探索|当极光遇见气辉...NASA宇航员拍下绝美画面
- “全麦面包”真假难辨:部分掺杂小麦粉 涉成分虚标
- 典韦新星元全面曝光,看完超清高能特效之后,玩家:吃土也要入手
- 本月底,对爱情从来不会强求,即使失败,也能坦然面对的4大星座
- 郭士强完成重磅签约!大牌外援重返CBA 广州队野心浮出水面
- 疫情|警惕!全球新冠累计超2199万例 欧洲疫情全面反弹
- 中超又一位名帅面临下课危机,下一轮或决定去留,替代者浮出水面
- 财险|亏损难止、保费增长滞缓,渤海财险面临生死存亡
- 男士补水面膜哪款效果好 男士控油补水面膜排行榜10强
- 战略观察员|国产JDAM公开亮相,已量产列装,我空军进入全面精准打击新时代
