15

I'm trying to achieve something as below.

package main

import (
    "fmt"
)

type MyStruct struct {
    Value int
}

func main() {
    x := []MyStruct{
        MyStruct{
            Value : 5,
        },
        MyStruct{
            Value : 6,
        },
    }
    var y []interface{}
    y = x // This throws a compile time error

    _,_ = x,y
}

This gives a compile time error:

sample.go:21: cannot use x (type []MyStruct) as type []interface {} in assignment

Why is this not possible?.If not is there any other way to hold generic object arrays in Golang?

tristan
  • 4,235
  • 2
  • 21
  • 45
Anuruddha
  • 3,187
  • 5
  • 31
  • 47
  • 2
    Because array of *a generic type* is not equal to array of *a struct*. Just use `var y interface{}` instead of array. Type `interface{}` can be used to store **any type of variable** in Golang. – putu Jun 02 '17 at 02:42
  • @putu thanks changing to interface{} solved the problem – Anuruddha Jun 02 '17 at 03:03
  • 2
    See https://golang.org/doc/faq#convert_slice_of_interface – Charlie Tumahai Jun 02 '17 at 03:51
  • Possible duplicate of [golang: slice of struct != slice of interface it implements?](https://stackoverflow.com/questions/12994679/golang-slice-of-struct-slice-of-interface-it-implements) – Adrian Jun 02 '17 at 13:24

1 Answers1

35

interface{} is stored as a two word pair, one word describing the underlying type information and one word describing the data within that interface:

enter image description here

https://research.swtch.com/interfaces

Here we see the first word stores the type information and the second the data within b.

Struct types are stored differently, they do not have this pairing. Their fields of a struct are laid out next to one another in memory.

enter image description here

https://research.swtch.com/godata

You cannot convert one to the other because they do not have the same representation in memory.

It is necessary to copy the elements individually to the destination slice.

https://golang.org/doc/faq#convert_slice_of_interface

To answer your last question, you could have []interface which is a slice of interfaces, where each interface is represented as above, or just interface{} where the underlying type held in that interface is []MyStruct

var y interface{}
y = x 

or

y := make([]interface{}, len(x))
for i, v := range x {
    y[i] = v
}
Zak
  • 5,515
  • 21
  • 33
  • Will this duplicate everything in RAM? I don't see pointers used so I guess everything is copied by value. – Adrian Moisa Apr 16 '23 at 17:16
  • 1
    If you use the second option: "or just interface{} where the underlying type held in that interface is []MyStruct" then slices are already reference types, so there would be no copying of the underlying data. If you copy your data out of the []MySlice and into []interface{}, then yes, you will have a copy of the data. – Zak Apr 21 '23 at 14:36