Sławosz
Sławosz

Reputation: 11687

Generic method to iterate over collection (slice) of structs

I have following code in Go:

type Foo struct { Id int }
type Bar struct { Id int }

func getIdsFoo(foos []Foo) {
  ids = make([]int, len(foos))
  // iterate and get all ids to ids array
}

func getIdsBar(bars []Bar) {
  ids = make([]int, len(bars))
  // iterate and get all ids to ids array
}

Is there a clever way to create a function getIds([]Idable) that can take any struct that have method GetId() implemented?

Upvotes: 2

Views: 1121

Answers (2)

thwd
thwd

Reputation: 24818

type Identifiable interface {
    GetId() int
}

func GatherIds(ys []Identifiable) []int {
    xs := make([]int, 0, len(ys))
    for _, i := range ys {
        xs = append(xs, i.GetId())
    }
    return xs
}

Upvotes: 3

deft_code
deft_code

Reputation: 59269

sort uses a design patter that might help you.

Create a function that works on an slice-like interface. Then create new types based off of a slice of your concrete types.

Hopefully, the code is more clear than my description. http://play.golang.org/p/TL6yxZZUWT

type IdGetter interface {
    GetId(i int) int
    Len() int
}

func GetIds(ig IdGetter) []int {
    ids := make([]int, ig.Len())
    for i := range ids {
        ids[i] = ig.GetId(i)
    }
    return ids
}

type Foo struct{ Id int }

type Bar struct{ Id int }

type FooIdGetter []Foo

func (f FooIdGetter) GetId(i int) int {
    return f[i].Id
}

func (f FooIdGetter) Len() int {
    return len(f)
}

type BarIdGetter []Bar

func (b BarIdGetter) GetId(i int) int {
    return b[i].Id
}

func (b BarIdGetter) Len() int {
    return len(b)
}

func main() {
    var f = []Foo{{5}, {6}, {7}}
    var b = []Bar{{10}, {11}, {12}}

    fmt.Println("foo ids:", GetIds(FooIdGetter(f)))
    fmt.Println("bar ids:", GetIds(BarIdGetter(b)))
}

There is still a bit more boilerplate than is pleasant, (Go generics... someday). It's greatest advantage is that new methods do not need to be added to Foo, Bar, or any future type you may need to work with.

Upvotes: 2

Related Questions