2

I am attempting to assign an array of structs of type Baz to an array of interfaces of type Bar embedded in a second struct of type Foo. I have not been able to find the exact information here or elsewhere googling. I have provided a minimum working example.

I get the following error:

$ go run main.go

./main.go:38: cannot use baz (type []*Baz) as type []Bar in argument to NewFoo

My apologies if my code is not idiomatic go and also if I have not confirmed exactly to standards for posting questions, this is my first post.

package main


import (
    "fmt"
)
type Foo struct {
    b []Bar
}



type Baz struct {
    a, b int
}

type Bar interface {
    Multiply() int
}

func (baz *Baz) Multiply() int{
    return baz.a * baz.b
}

func NewFoo(bar []Bar) *Foo{
    return &Foo{b: bar}
}
func NewBaz() []*Baz {
    bazes := make([]*Baz, 2)
    bazes[0] = &Baz{a: 1, b: 2}
    bazes[1] = &Baz{a: 3, b: 4}
    return bazes
}

func main() {

    baz := NewBaz()
    foo := NewFoo(baz)
    for _, f := range foo.b {
        fmt.Println("Foo.Multiply ", f.Multiply())
    }
}

UPDATE: I approved the duplicate vote after further reading and understanding the suggested related posts. Thank you to those who pointed me in that direction. For future interested readers, my final implementation consistent with my use case is as follows:

package main

import (
    "fmt"
)

type Foo struct {
    b []Bar
}

type Baz struct {
    a, b int
}

type Bar interface { //
    Multiply() int
}

func (baz *Baz) Multiply() int {
    return baz.a * baz.b
}

func NewFoo(bar []*Baz) *Foo{
    f := &Foo{}
    f.b = make([]Bar, 2)
    fmt.Println("len(bar) ", len(bar), "len(f.b)", len(f.b) )
    for i, _ := range f.b {
        f.b[i] = bar[i]

    }
    return f
}

func MakeBaz() []*Baz {
    bazes := make([]*Baz, 2)
    bazes[0] = NewBaz(1, 2)
    bazes[1] = NewBaz(3, 4)
    return bazes
}

func NewBaz(aa, bb int) *Baz {
    return &Baz{a: aa, b: bb}
}

func main() {
    baz := MakeBaz()
    foo := NewFoo(baz)
    fmt.Printf("%v\n", foo)
    for _, f := range foo.b {
        fmt.Println("Foo.Multiply ", f.Multiply())
    }
}
Ben
  • 21
  • 4

2 Answers2

0

There's a couple of different ways to do this, but the most straightforward is to embed type Baz with Bar. Baz can now multiply() and has two fields (a, b). Your code would look something like this:

package main

import (
    "fmt"
)

type Foo struct {
    b []*Baz
}

type Baz struct {
    Bar
    a, b int
}

type Bar interface {
    Multiply() int
}

func (baz *Baz) Multiply() int {
    return baz.a * baz.b
}

func NewFoo(bar []*Baz) *Foo {
    return &Foo{b: bar}
}
func NewBaz() []*Baz {
    bazes := make([]*Baz, 2)
    bazes[0] = &Baz{a: 1, b: 2}
    bazes[1] = &Baz{a: 3, b: 4}
    return bazes
}

func main() {
    baz := NewBaz()
    foo := NewFoo(baz)
    for _, f := range foo.b {
        fmt.Println("Foo.Multiply ", f.Multiply())
    }
}

GoPlay here: https://play.golang.org/p/lia0ZS81TO

Great first question, by the way.

william.taylor.09
  • 2,145
  • 10
  • 17
  • Thank you for the information! I will try your solution and compare it with the related questions as per @eugenioy 's, comment. p.s. Thank you for the encouraging words! – Ben Jun 06 '17 at 20:05
  • No problem! Make sure to upvote answers that contribute to your question, and "select" an answer if appropriate! – william.taylor.09 Jun 06 '17 at 20:23
  • I upvoted both responses since they were both helpful, however, because my reputation is below 15, stackoverflow told me it would not show up publicly. – Ben Jun 06 '17 at 22:26
0

The error you are getting:

cannot use baz (type []*Baz) as type []Bar

Is because Go won't let you assign an array of Baz to an array of Bar, even when it'd let you assign a Baz to a Bar variable.

To see this in a more simple form, this works fine:

var oneBaz *Baz = &Baz{a: 1, b: 2} 
var oneBar Bar = oneBaz

Because the type Baz satisfies the Bar interface and you can assign a Baz object to a Bar variable.

But this does not work (even if it'd looks like it could work):

var bazArray []*Baz = make([]*Baz, 2)
var barArray []Bar = bazArray

It will throw the same error you are seeing.

In order to make this work, you'd probably need to implement one of the solutions listed in this related question:

Type converting slices of interfaces in go

eugenioy
  • 11,825
  • 28
  • 35
  • thanks for the explanation and reply! I will take a look at the related questions and see if I the alternatives are a better choice for my use case. – Ben Jun 06 '17 at 20:01