this question is related to Passing struct with anonymous field in Go but different in that I am dealing with a function that handles an array of Parent items rather than just one struct, ie:
package main
import "fmt"
type Parent struct {
Dad string
}
type Child struct {
Parent
Son string
}
func myfunc(data []Parent) {
for n, _ := range data {
fmt.Printf("Dad is %s\n", data[n].Dad)
}
}
func main() {
data := make([]Child, 2)
data[0].Dad = "pappy"
data[0].Son = "sonny"
data[1].Dad = "daddy"
data[1].Son = "billy"
myfunc(data)
}
I tried to cast data to an array of Parents like myfunc([]Parent(data))
but that didnt work and obviously the solution of myfunc(data.Parent)
wont work on an array.
Is there a reasonable solution to this in golang without resorting to creating a new slice or generics which are not out of beta yet?
Cheers
You cannot do this even with generics. data[n].Dad
will not work.
The reasonable way to deal with it is to use an interface, but still, you have to create an interface slice for it:
type WithDad interface {
GetDad() string
}
func (p Parent) GetDad() string {return p.Dad}
func myFunc(data []WithDad) {
...
}
...
arr:=make([]WithDad,0,len(data))
for _,x:=range data {
arr=append(arr,x)
}
myFunc(arr)
The reason for this is how the type system works and how slices are passed around. The slice []Child
points to an array where each entry is a Child
. A function that takes []Parent
expects a slice whose elements are Parent
, which is a different type, so you cannot pass one for the other.
The slice []WithDad
points to an array where each entry is an interface. Each such entry points to the Child
or Parent
entry in another slice.
Just for completeness I made a complete version of Burak Serdar code I got working (I like it when full working examples are posted for me to cut and paste later:P)... note I deliberately return a pointer to the Parent
because in practice its likely you will want to work on that complete struct and not just read 1 field.
package main
import "fmt"
type WithDad interface {
GetDad() *Parent
}
type Parent struct {
Dad string
}
func (p *Parent) GetDad() *Parent {
return p
}
type Child struct {
Parent
Son string
}
func (c *Child) GetDad() *Parent {
return &c.Parent
}
func myfunc(data []WithDad) {
for n, _ := range data {
fmt.Printf("Dad is %s\n", data[n].GetDad().Dad)
}
}
func main() {
data := make([]WithDad, 2)
data[0] = &Child{Parent: Parent{Dad: "pappy"}, Son: "sonny"}
data[1] = &Child{Parent: Parent{Dad: "daddy"}, Son: "billy"}
myfunc(data)
}
Your structure with Child being a composite of Parent and a string (which I guess contains the name) makes little sense. A child is not a parent plus their name. In fact you only have one concept, namely Person, who potentially has a parent. Please consider the following approach:
package main
import "fmt"
type Person struct {
Name string
Parent *Person
}
func myfunc(data []Person) {
for n, _ := range data {
fmt.PrintLn("My name is", n.Name)
if n.Parent != nil {
fmt.PrintLn("My dad is", n.Parent.Name)
}
}
}
func main() {
data := make([]Person, 2)
data[0].Name = "daddy"
data[1].Name = "billy"
data[1].Parent = &data[0]
myfunc(data)
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.