Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make a struct "range-able"?

Tags:

go

type Friend struct {
    name string
    age  int
}

type Friends struct {
    friends []Friend
}

I'd like to make Friends range-able, that means, if I have a variable my_friends with type Friends, I can loop though it with:

for i, friend := range my_friends {
    // bla bla
}

is it possible in Go?

like image 814
wong2 Avatar asked Oct 15 '12 11:10

wong2


2 Answers

Has Friends to be a struct? Otherwise simply do

type Friends []Friend
like image 163
themue Avatar answered Oct 14 '22 16:10

themue


Beware: As deft_code mentions, this code leaks a channel and a goroutine when the loop breaks. Do not use this as a general pattern.


In go, there is no way to make an arbitrary type compatible for range, as range only supports slices, arrays, channels and maps.

You can iterate over channels using range, which is useful if you want to iterate over dynamically generated data without having to use a slice or array.

For example:

func Iter() chan *Friend {
   c := make(chan *Friend)
   go func() {
      for i:=0; i < 10; i++ {
        c <- newFriend()
      }
      close(c)
   }()
   return c
}

func main() {
  // Iterate 
  for friend := range Iter() {
    fmt.Println("A friend:", friend)
  }
}

That's the closest thing you can have to make something 'rangeable'.

So a common practice is to define a method Iter() or something similar on your type and pass it to range.

See the spec for further reading on range.

like image 22
nemo Avatar answered Oct 14 '22 17:10

nemo