Avoiding leaks

It is a good idea to allow the loop to end in order to avoid goroutine and resource leakage. Some of these issues are as follows:

 

An easy solution to this problem is to always use context.Context so that you have a well-defined exit point for the goroutine:

func NewGenInt64(ctx context.Context) genInt64 {
g := genInt64{ch: make(chan int64)}
go func() {
for i := int64(0); ; i++ {
select {
case g.ch <- i:
// do nothing
case <-ctx.Done():
close(g.ch)
return
}
}
}()
return g
}

This can be used to generate values until there is a need for them and cancel the context when there's no need for new values. The same pattern can be applied to a version that returns a channel. For instance, we could use the cancel function directly or set a timeout on the context:

func main() {
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*100)
defer cancel()
g := NewGenInt64(ctx)
for i := range g.ch {
go func(i int64) {
fmt.Println(i, g.Next())
}(i)
}
time.Sleep(time.Second)
}

The generator will produce numbers until the context that's provided expires. At this point, the generator will close the channel.