Amine Kerkeni
Amine Kerkeni

Reputation: 924

How to initialize a array of interface in golang?

I want to initialize a map containing a list of interface without having to add them one by one:

type Pixel struct {
    X float64
    Y float64
}

type Vertex struct {
    X float64
    Y float64
    Z float64
}
type testpair struct {
    filename       string
    values     []interface{}
}
var tests = map[string]testpair{
   "test1": {
               filename: "file1.csv",
               values:  []Pixel{
                           {X: 12.5, Y: 23.4},
                           {X: 17.2, Y: 7.9},
                      }
            },
   "test2": {
               filename: "file2.csv",
               values:  []Vertex{
                           {X: 10.7, Y: 13.3, Z: 25.1},
                           {X: 18.3, Y: 16.9, Z: 16.4},
                      }
            }, 
}

The compiler would output such an error:

cannot use []Pixel literal (type []Pixel) as type []interface {} in field value

If I switch []interface{} to []Pixel, I can initialize the map but I can do it only with a unique type Pixel or Vertex.

Is there a way to force the compiler to accept array initialization with a specific struct while declaring it as an array of interface?

Upvotes: 9

Views: 21387

Answers (4)

Macilias
Macilias

Reputation: 3543

I had the same problem but was about to use primitives so this suggested solution here want work. In that case I helped my self out with:

args := make([]interface{}, 2)
args[0] = "some string"
args[1] = 1 //some int

Upvotes: 1

Hamdi Belhassen
Hamdi Belhassen

Reputation: 9

To be able to initialize you need to input a type to the interface and not an array of type, so suggest you to change as follow:

    type Pixel struct {
    X float64
    Y float64
}
type Pixels []Pixel

type Vertex struct {
    X float64
    Y float64
    Z float64
}
type Vertexs []Vertex
type testpair struct {
    filename string
    values   interface{}
}
var tests = map[string]testpair{
    "test1": {
        filename: "file1.csv",
        values: Pixels{
            Pixel{X: 12.5, Y: 23.4},
            Pixel{X: 17.2, Y: 7.9}}},
    "test2": {
        filename: "file2.csv",
        values: Vertexs{
            Vertex{X: 10.7, Y: 13.3, Z: 25.1},
            Vertex{X: 18.3, Y: 16.9, Z: 16.4}}}}

Upvotes: 0

bereal
bereal

Reputation: 34292

If you have to create a slice of values for passing to something that requires a slice of interface{} (which, depending on the context, may or may not be appropriate design) or a slice of any more specific interface, you have to specify each element fully, like this:

[]interface{}{ 
    Pixel{X: 12.5, Y: 23.4},
    Pixel{X: 17.2, Y: 7.9},
}

That also means that you can pass things like:

[]interface{}{
    Pixel{X: 12.5, Y: 23.4},
    Vertex{X: 10.7, Y: 13.3, Z: 25.1},
}

which is hardly something you intended, and compiler won't warn you. I don't see that a big deal for the testing code, though.

Upvotes: 18

Volker
Volker

Reputation: 42431

Is there a way to force the compiler to accept array initialization with a specific struct while declaring it as an array of interface?

No. Basically you cannot force the Go compiler to anything.

See also the FAQ: https://golang.org/doc/faq#convert_slice_of_interface

You must supply a []interface{}.

But please stop doing this and come up with something not requiring the empty interface.

Upvotes: 3

Related Questions