Here is my test code
package main
import "fmt"
type Node interface {
sayHello()
}
type Parent struct {
Name string
}
type Child struct {
Parent
Age int
}
type Children []Child
func (p Parent) sayHello() {
fmt.Printf("Hello my name is %s
", p.Name)
}
func (p Child) sayHello() {
fmt.Printf("Hello my name is %s and I'm %d
", p.Name, p.Age)
}
func makeSayHello(n Node) {
n.sayHello()
}
func sayHellos(list []Node) {
for _, p := range list {
makeSayHello(p)
}
}
func main() {
children := []Child{Child{Parent: Parent{Name: "Bart"}, Age: 8}, Child{Parent: Parent{Name: "Lisa"}, Age: 9}}
for _, c := range children {
c.sayHello()
}
makeSayHello( Parent{"Homer"} )
sayHellos( []Node{Parent{"Homer"}} )
sayHellos( []Node{Parent{"Homer"},Child{Parent:Parent{"Maggy"},Age:3}} )
sayHellos( children ) // error : cannot use children (type []Child) as type []Node in argument to sayHellos
}
link https://play.golang.org/p/7IZLoXjlIK
I don't get it. Let's say I have a []Child I cannot modify and I want use it with un function accepting []Parent. Why do I have an type error ?
If I can't or don't want this solution by changing
children := []Child{...}
to
children := []Node{...}
What can I do to transform the []Child to []Node ? It is not already ? Do I have to do another []Node to copy my elements in ? I naïvely try children.([]Node) or []Node(children) without success ...
An array of structs (such as []Child
) has very different memory layout comparing to an array of interfaces (such as []Node
). So Go doesn't do []Child
to []Node
conversion implicitly, you have to do it yourself:
nodes := make([]Node, len(children), len(children))
for i := range children {
nodes[i] = children[i]
}
sayHellos(nodes)
BTW in the example you provided it would be more efficient to call sayHello
directly:
for _, child := range children {
child.sayHello()
}
Probably this is what you should do in your program as well.