Use []T as []interface{}

How can i use []T as []interface{}?

I want to be able to do the following

s := []rune{'a', 'b', 'c'}
fmt.Println(s...)

You cannot. You have to convert:

rs := []rune{'a', 'b', 'c'}
vs := make([]interface{}, len(rs)
for i, r := range rs {
    vs[i] = r
}
fmt.Println(vs...)

Why?

If T can be assigned to interface{}, then why []T can’t be assigned to []interface{}?

I’m working on an example now :slight_smile:

The issue is that the memory layout of a []rune is completely different than that of []interface{}. A []rune contains a pointer to an array of 4-byte runes positioned back-to-back in memory. An interface{} “behind the scenes” is really:

type emptyInterface struct {
    *_type
    unsafe.Pointer
}

so a slice of []interface{} is a slice of 16-byte (on a 64-bit system, 8-byte on a 32-bit system) structs back-to-back in memory. You cannot just cast a []rune to an []interface{} because the memory layout is completely different.

Example: https://play.golang.org/p/yjUtF9CVdyU

2 Likes

If i can assign T to interface{} then why I can’t assign []T to []interface{}

Because in order to assign a rune to an interface{}, the Go runtime allocates a pointer to a rune and then stores that pointer in the interface{} as well as the rune type information. The memory layout is completely different. The runtime handles the magic that converts concrete types to interfaces but the runtime does not convert concrete types like slices from one type to another.

still unclear. i can assign a T to interface{}. Then i can’t have a slice of them.

This is inherently a complicated subject. Yes, pun intended.:slight_smile:

It has to do with covariance and invariance and this same issue has caused many lost hours of productivity for new players in Java, C# and just about every other OOesque language that includeds generics.

Now, I know Go does not have generics, yet. But it is the same issue at hand.

The TL;DR

you can assert any interface{} reference to a type because **every type is an interface{}is covariant because every SomeType is an interface{} and every type is an interface{}

[]interface{} can not be asserted to a []SomeType because []interface{} is a separate type and completely unrelated to []AnyOtherType.

I know this is a link to a question about Java, but it shows two things, one that this is a reaccuring confusing issue since 2004 in the Java world. When Java got generics.

Two it explains the idea of covariant and invariant very well and gives you a place to start to do more research on a complex set theory idea for yourself.

Now imagine how confusing it is going to get with Go if they have the same limitations that Java, C#, Scala, etc have with their generic implementations.

i still don’t understand.

It was stated in the official Go F.A.Q.:
https://golang.org/doc/faq#convert_slice_of_interface

if that is not clear, then you can do a research on internal memory representation for slices and interfaces.