Go 1.15 中,小整数转换为接口值的疑问

quanquan616 · 2020-09-29 10:29:38 · 967 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2020-09-29 10:29:38 的主题,其中的信息可能已经有所发展或是发生改变。

在站长的公众号里,看到了一篇关于 "Go 1.15 中,小整数转换为接口值时,将不再进行内存分配" 的文章。
原文地址:https://mp.weixin.qq.com/s/1r0nt8nA3foDRRrbRp4omg

我自己闲得蛋疼,折腾了一下。代码运行后,为什么每一个打印出来的内存地址都会不一样?
OS: ubuntu server 18.04 LTS 64bit
go version: 1.15.2
我自己折腾的代码如下:

package main

import "fmt"

func main() {
    var slice = make([]interface{}, 3)

    slice[0] = 1
    slice[1] = 128
    slice[2] = 256

    for i := 0; i < 3; i++ {
        fmt.Printf("%p, ", &slice[i])

    }

    println()
}

/*
运行结果:
0xc00005c150, 0xc00005c160, 0xc00005c170,
*/


运行结果的截图:
1.png

按照 Go 1.15 开始的特性:小整数转换为 interface{} 将不再需要进行内存分配。
那为什么打印出来的 3 个地址都是不一样的?如果说 256 这个值打印出来的地址有变化,那是好理解的。但是 1 和 128,不都是在小整数范围内的,为什么它俩的内存地址不一样?
恳请大佬解惑,还是我哪里打开姿势不对?


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

967 次点击  ∙  1 赞  
加入收藏 微博
5 回复  |  直到 2020-10-01 11:26:51
fdsa
fdsa · #1 · 5年之前

你这里打印的是 slice 中元素的地址,都是连续的,看着没什么问题。至于interface{},我就不清楚怎么查了,怀疑取值时go内部会转换掉,你很难拿到。要不一起看看 https://research.swtch.com/interfaces 研究下。

focusonline
focusonline · #2 · 5年之前

我觉得吧, make只是分配一个interface{}的数组, 但是数组的值都是nil, 这个应该理解成void*, 这个地址有3个很正常, 指针本身也有地址的.你后来的赋值, 把小整数赋值过去, 不分配内存的意思我相信应该是这个小整数已经作为常量池的数据 固定在内存某个地方, 你的interface是直接指向这里的, 而不用另外新分配的动态变量地址.

quanquan616
quanquan616 · #3 · 5年之前

刚才修改了一些代码,并用站长文章中所写的 bench 思路尝试了一下,确实没有分配内存了。我这个折腾,实际上是在获取数组的内存地址。

void * 的角度来看,就是指针一个个往后挪,获取到的是数组中,每个索引的地址了。

无标题.jpg

byssh1989
byssh1989 · #4 · 5年之前

兄弟,我真是闲的跟你一样蛋疼……这东西真不好测试,为了获取到interface中的真实data地址,我也是头痛…… 经过各种google,终于在万能的stackoverflow上看到一个好办法…… 附上stackoverflow地址:https://stackoverflow.com/questions/57696977/how-to-get-a-pointer-to-the-underlying-value-of-an-interface-in-go 。 附上wide的测试代码地址:https://wide.b3log.org/playground/49b4de79f363ef7c1415d2372f972344.go

quanquan616
quanquan616 · #5 · 5年之前

确实是好文章,感谢大佬分享。其实 2 楼的大佬,通过 C 语言的方式,已经提醒我了。

我个人的理解:直接获取切片中的元素地址,它其实是在访问这个切片,而不是在访问那个特殊的静态小整数数组。

func dummy(b int) interface{} 函数将一个 int 类型转换为借口类型,如果这个数值是 [0 ~ 255] 那么刚好就符合了站长文章中提及的:小整数转换为接口类型时,将不再需要额外的内存分配了。个人想想:因为这个小整数变成接口类型时,就存在于一个特殊的静态数组中。

我个人感觉,这个功能咋有点鸡肋 :sweat_smile: 。只有当小整数转换为接口类型时,才不会有额外的内存分配。直接初始化小整数时,还是会有内存分配。整数转换为接口类型,也是要消耗资源(虽然这个消耗很小很小)。直接让小整数不转换接口类型就能指向这个特殊的静态数组,它不香吗?没能理解官方为什么要这么设置。

添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传