Create a gist now

Instantly share code, notes, and snippets.

Embed
What would you like to do?
package main
import (
"context"
"fmt"
)
func gen(ctx context.Context) <-chan int {
ch := make(chan int)
go func() {
var n int
for {
select {
case <-ctx.Done():
return
case ch <- n:
n++
}
}
}()
return ch
}
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
for n := range gen(ctx) {
fmt.Println(n)
if n == 5 {
cancel()
break
}
}
}
@kylehq

This comment has been minimized.

Show comment
Hide comment
@kylehq

kylehq Jan 31, 2017

Hi Jaana, thanks so much for putting all these together. I'd like to ask a question in regards to the above and your post https://rakyll.org/leakingctx/.

We can avoid the problem by signalling the internal goroutine with a stop channel but there is a better solution: cancellable contexts.

Can you explain to me why it's better to pass a context to the gen() function rather than a stop chan struct{}? The gen function would still have the same method changes, both ways will use a single dependency and the stop can also be deferred to ensure no goroutine leaks.

Is this just a new convention? Is there a performance gain to using the context instead? Any thoughts would be most welcome =]
Thanks Kyle

kylehq commented Jan 31, 2017

Hi Jaana, thanks so much for putting all these together. I'd like to ask a question in regards to the above and your post https://rakyll.org/leakingctx/.

We can avoid the problem by signalling the internal goroutine with a stop channel but there is a better solution: cancellable contexts.

Can you explain to me why it's better to pass a context to the gen() function rather than a stop chan struct{}? The gen function would still have the same method changes, both ways will use a single dependency and the stop can also be deferred to ensure no goroutine leaks.

Is this just a new convention? Is there a performance gain to using the context instead? Any thoughts would be most welcome =]
Thanks Kyle

@Xeoncross

This comment has been minimized.

Show comment
Hide comment
@Xeoncross

Xeoncross Jul 29, 2017

@kylehq, looks like the process is more about handling passing channels over a number of functions (some of which may be third party) like when dealing with a HTTP request: https://blog.golang.org/context/google/google.go

Still looks like a standard stop chan struct{} would work, but the context can also pass additional values all the way through so it combines a signaler + values.

Xeoncross commented Jul 29, 2017

@kylehq, looks like the process is more about handling passing channels over a number of functions (some of which may be third party) like when dealing with a HTTP request: https://blog.golang.org/context/google/google.go

Still looks like a standard stop chan struct{} would work, but the context can also pass additional values all the way through so it combines a signaler + values.

@gerep

This comment has been minimized.

Show comment
Hide comment
@gerep

gerep Nov 24, 2017

Is it required to call cancel() inside the n == 5 conditional even when you are using break to escape the loop and using defer cancel()?

gerep commented Nov 24, 2017

Is it required to call cancel() inside the n == 5 conditional even when you are using break to escape the loop and using defer cancel()?

@ThisisYang

This comment has been minimized.

Show comment
Hide comment
@ThisisYang

ThisisYang Jan 26, 2018

@gerep It is duplicated I believe.
check the example of WithCancel doc: https://golang.org/pkg/context/#WithCancel

ThisisYang commented Jan 26, 2018

@gerep It is duplicated I believe.
check the example of WithCancel doc: https://golang.org/pkg/context/#WithCancel

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment