如何在golang中为对象分配嵌入式接口[重复]

This question already has an answer here:

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
", foo)
    for _, f := range foo.b {
        fmt.Println("Foo.Multiply ", f.Multiply())
    }
}
</div>

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.

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