Reputation: 67
I can't understand the logic of this example in Go Concurrency Patterns: Context
func httpDo(ctx context.Context, req *http.Request, f func(*http.Response, error) error) error {
// Run the HTTP request in a goroutine and pass the response to f.
c := make(chan error, 1)
req = req.WithContext(ctx)
go func() { c <- f(http.DefaultClient.Do(req)) }()
select {
case <-ctx.Done():
<-c // Wait for f to return.
return ctx.Err()
case err := <-c:
return err
}
}
Before that it is said that:
The
Done
method returns a channel that acts as a cancellation signal to functions running on behalf of theContext
: when the channel is closed, the functions should abandon their work and return.
It looks like the equivalent of awaiting of <-c
only, without case <-ctx.Done()
at all. So, what is the point?
Upvotes: 5
Views: 2096
Reputation: 22174
The context may cancel the Do
call. The case <-ctx.Done()
unambiguously identify that this happened.
Indeed, we may assume that the Do
call would then return a nil
http.Response
, and that the function f
would then return an error when this happens. But we wouldn’t know why f
received a nil
http.Response
as input argument.
The instruction case err := <-c:
handles the case when the error is produced inside f
.
Upvotes: 3
Reputation: 1642
It is not equivalent to awaiting <-c
only. The example returns a different value (ctx.Err()
) when the context is closed.
Upvotes: 1