While writing two methods (one for a slice and one for a string map) I realized the implementation for both methods is identical and the only thing that changes is the prototype of the functions.
I'm trying to avoid repeating it and originally I thought of the following (see the FIXME part):
package main
import (
"fmt"
"strings"
)
type SomethingList []*Something
type SomethingMap map[string]*Something
type Something struct {
ID string
Type int
}
func (sl SomethingList) GetIDsString() string {
return getIDsString(sl)
}
func (sm SomethingMap) GetIDsString() string {
return getIDsString(sm)
}
func getIDsString(elements interface{}) string {
var ids []string
// FIXME: Yes, I know I can't iterate over an interface
for element = range elements {
ids = append(ids, element.ID)
}
return strings.Join(ids, ",")
}
func main() {
s1 := Something{ID: "ABC", Type: 1}
s2 := Something{ID: "DEF", Type: 1}
sl := SomethingList{&s1, &s2}
sm := SomethingMap{s1.ID: &s1, s2.ID: &s2}
fmt.Println(sl.GetIDsString())
fmt.Println(sm.GetIDsString())
}
The important part is the function getIDsString
which basically takes the ID field of the struct and concatenates it's content across all the members of the slice or map.
I realize now after reading a bit about how interfaces work (yes, I'm quite a newbie in Go as is probably obvious already :-)) that this is not going to work, as Go is statically typed and I can't simply change the types on runtime. Also the interfaces don't allow me to iterate. I've been able to get close using a loop that iterates using the Len() method on the reflect.ValueOf and Index() to access each element. But Index() doesn't work on the string map.
What would be the most idiomatic way of solving this without duplicating much code?
Thanks!