Object 返回接口{}而不是int64时的额外分配

Object 返回接口{}而不是int64时的额外分配,object,memory,go,types,allocation,Object,Memory,Go,Types,Allocation,我有一个函数,它生成一个随机的int64,并将其作为接口{}返回,如下所示: func Val1(rnd rand.Source) interface{} { return rnd.Int63() } 现在考虑这个函数,它做同样的事情,但是返回一个 func Val2(rnd rand.Source) int64 { return rnd.Int63() } 我用这个(go test-bench=.-benchmem)对这两个函数进行了基准测试: Val1()中的额外分配从何而来?返

我有一个函数,它生成一个随机的
int64
,并将其作为
接口{}
返回,如下所示:

func Val1(rnd rand.Source) interface{} {
 return rnd.Int63() 
} 

现在考虑这个函数,它做同样的事情,但是返回一个<代码>

func Val2(rnd rand.Source) int64 {
 return rnd.Int63()
}
我用这个(
go test-bench=.-benchmem
)对这两个函数进行了基准测试:


Val1()
中的额外分配从何而来?返回
接口{}
时是否可以避免此问题

接口值是引擎盖下的包装,是存储在接口值及其类型描述符中的一对具体值

有关更多信息,请阅读以下内容:

因此,如果要返回
接口{}
类型的值,将隐式创建
接口{}
值(如果返回的值尚未属于该类型),该值将保存整数及其表示
int64
类型的类型描述符。你无法避免这一点

接口{}
是一种特殊的接口类型(具有0个方法)。正如您在基准测试输出中看到的,它的值只有8个字节。其他接口类型的大小更大(双倍),因为它们还必须标识接口类型的静态方法集(除了动态类型和值)

另外,请务必查看此信息性答案:


如果您想了解有关实现/内部构件的更多信息,我建议您发布以下帖子:

接口值是一个包装器,一对存储在接口值及其类型描述符中的具体值

有关更多信息,请阅读以下内容:

因此,如果要返回
接口{}
类型的值,将隐式创建
接口{}
值(如果返回的值尚未属于该类型),该值将保存整数及其表示
int64
类型的类型描述符。你无法避免这一点

接口{}
是一种特殊的接口类型(具有0个方法)。正如您在基准测试输出中看到的,它的值只有8个字节。其他接口类型的大小更大(双倍),因为它们还必须标识接口类型的静态方法集(除了动态类型和值)

另外,请务必查看此信息性答案:


如果您想了解有关实现/内部结构的更多信息,我建议您发布以下帖子:

一如既往@icza您值得拥有黄金价值一如既往@icza您值得拥有黄金价值
func BenchmarkVal1(b *testing.B) {
    var rnd = rand.NewSource(time.Now().UnixNano())
    for n := 0; n < b.N; n++ {
        Val1(rnd)
    }
}

func BenchmarkVal2(b *testing.B) {
    var rnd = rand.NewSource(time.Now().UnixNano())
    for n := 0; n < b.N; n++ {
        Val2(rnd)
    }
}
BenchmarkVal1-4    50000000         32.4 ns/op         8 B/op          1 allocs/op
BenchmarkVal2-4    200000000        7.47 ns/op         0 B/op          0 allocs/op