I have a function that generates a random int64
and returns it as an interface{}
like this:
func Val1(rnd rand.Source) interface{} {
return rnd.Int63()
}
now consider this function, which does the same thing but returns a int64
func Val2(rnd rand.Source) int64 {
return rnd.Int63()
}
I benchmarked the two functions with this (go test -bench=. -benchmem
) :
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)
}
}
and got folowing results:
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
Where does the extra allocation in Val1()
come from ? Can it be avoided when returning an interface{}
?
An interface value is a wrapper under the hood, a pair of the concrete value stored in the interface value and its type descriptor.
Read this for more information: The Laws of Reflection #The representation of an interface
So if you want to return a value of interface{}
type, an interface{}
value will be implicitly created (if the value being returned is not already of that type), which will hold the integer number and its type descriptor denoting the int64
type. You can't avoid this.
interface{}
is a special interface type (having 0 methods). Its value is only 8 bytes as you see on the benchmark output. Other interface types have larger size (double) as they also have to identify the static method set of the interface type (besides the dynamic type and value).
Also be sure to check out this informative answer: Go: What's the meaning of interface{}?
If you want more information about the implementation / internals, I recommend this post: How Interfaces Work in Golang