4 ms·
What's the limit here? That code is written like that because it's the only way to write code like that. You have a channel producing items, it will produce it
by Philip-J-Fry 3y ago
What's the limit here?
That code is written like that because it's the only way to write code like that. You have a channel producing items, it will produce items for as long as the channel is open. You have a context to propagate cancellation.
You code gets bigger but it doesn't explode in size as this boilerplate is static in size regardless of what computation you're doing with those items.
You can improve that code by the way by fixing a bug and reducing the lines.
L:
for {
select {
case <-ctx.Done():
break L
case item, ok := <-channel:
if !ok {
break L
}
// code goes here
}
}
If you think there's a way to write that code any more concise than that, then there isn't. I don't see how this is an issue. The fact that there's pretty much one way to write this code makes it so much easier to parse when reading code that uses this pattern. To me, that's great.
- deleted 3y ago[deleted]
- valczir 3y agoalternatively: var errClosed = errors.New("closed") func doAThing[T any](ctx context.Context, c chan T) (T, error) { // the generics are not necessary, but they're also not awful for // DRYing up this type of a select. select { case <-ctx.Done(): var empty T return empty, fmt.Errorf("could not doAThing: %w", ctx.Err()) case item, ok := <-c: if !ok { var empty T return empty, fmt.Errorf("channel of type %T is done: %w", empty, errClosed) } return item, nil } } // ... and later... for { item, err := doAThing(ctx, channel) if err != nil { break } // code goes here } I dislike labeled loops, naked returns, and else statements, so this is the pattern I use.
- anacrolix 3y agoNo. Just no.