I need help with making this work for any type.
I have got a function I need to accept other types that have ID
property.
I have tried using interfaces but that did not work for my ID
property case. Here is the code:
package main
import (
"fmt"
"strconv"
)
type Mammal struct{
ID int
Name string
}
type Human struct {
ID int
Name string
HairColor string
}
func Count(ms []Mammal) *[]string { // How can i get this function to accept any type not just []Mammal
IDs := make([]string, len(ms))
for i, m := range ms {
IDs[i] = strconv.Itoa(int(m.ID))
}
return &IDs
}
func main(){
mammals := []Mammal{
Mammal{1, "Carnivorious"},
Mammal{2, "Ominivorious"},
}
humans := []Human{
Human{ID:1, Name: "Peter", HairColor: "Black"},
Human{ID:2, Name: "Paul", HairColor: "Red"},
}
numberOfMammalIDs := Count(mammals)
numberOfHumanIDs := Count(humans)
fmt.Println(numberOfMammalIDs)
fmt.Println(numberOfHumanIDs)
}
I get this
error prog.go:39: cannot use humans (type []Human) as type []Mammal in argument to Count
See Go Playground for more details here http://play.golang.org/p/xzWgjkzcmH
Use interfaces instead of concrete types, and use embedded interfaces so the common methods do not have to be listed in both types:
type Mammal interface {
GetID() int
GetName() string
}
type Human interface {
Mammal
GetHairColor() string
}
And here is the implementation of these interfaces based on your code which uses embedded types (structs):
type MammalImpl struct {
ID int
Name string
}
func (m MammalImpl) GetID() int {
return m.ID
}
func (m MammalImpl) GetName() string {
return m.Name
}
type HumanImpl struct {
MammalImpl
HairColor string
}
func (h HumanImpl) GetHairColor() string {
return h.HairColor
}
But then of course in your Count()
function you can only refer to the method and not the field of the implementation:
IDs[i] = strconv.Itoa(m.GetID()) // Access ID via the method: GetID()
And creating your slices of Mammals and Humans:
mammals := []Mammal{
MammalImpl{1, "Carnivorious"},
MammalImpl{2, "Ominivorious"},
}
humans := []Mammal{
HumanImpl{MammalImpl: MammalImpl{ID: 1, Name: "Peter"}, HairColor: "Black"},
HumanImpl{MammalImpl: MammalImpl{ID: 2, Name: "Paul"}, HairColor: "Red"},
}
Here is the complete working code on Go Playground.
You can't do precisely what you ask for in Go. Closest way to do things in Go would be something like this as shown in code below:
type Ids interface{
Id() int
}
func (this Mammal) Id() int{
return this.ID
}
func (this Human) Id() int{
return this.ID
}
func Count(ms []Ids) *[]string {
...
IDs[i] = strconv.Itoa(int(m.Id()))
...
}
func main(){
mammals := []Ids{
Mammal{1, "Carnivorious"},
Mammal{2, "Ominivorious"},
}
humans := []Ids{
Human{ID:1, Name: "Peter", HairColor: "Black"},
Human{ID:2, Name: "Paul", HairColor: "Red"},
}
...
}
here is the working example