q.RecvCtx and q.RecvCtxE¶
Channel receive that honours context cancellation. Blocks on a select between ctx.Done() and the channel; whichever fires first wins.
Signatures¶
func RecvCtx[T any](ctx context.Context, ch <-chan T) T
func RecvCtxE[T any](ctx context.Context, ch <-chan T) ErrResult[T]
// Runtime helper (usable standalone, NOT rewritten):
func RecvRawCtx[T any](ctx context.Context, ch <-chan T) (T, error)
What q.RecvCtx does¶
rewrites to:
RecvRawCtx is the runtime helper the rewriter inlines the call to. It's a plain function — select { <-ctx.Done() | <-ch } — so user code can call it directly when the raw (T, error) tuple is wanted.
Three outcomes:
| Event | Return value |
|---|---|
ch delivers v |
(v, nil) |
| ch is closed | (zero, q.ErrChanClosed) |
| ctx is cancelled/deadline | (zero, ctx.Err()) — Canceled or DeadlineExceeded |
Chain methods on q.RecvCtxE¶
Reuses ErrResult[T] — identical vocabulary to q.TryE (the captured err is the Raw helper's output, which may be ctx.Err() or q.ErrChanClosed).
v := q.RecvCtxE(ctx, ch).Wrap("waiting for job")
v := q.RecvCtxE(ctx, ch).Catch(func(e error) (Job, error) {
if errors.Is(e, q.ErrChanClosed) {
return Job{}, nil // normal shutdown, recover with empty
}
return Job{}, e // bubble ctx cancellation
})
See q.Try → chain methods for full method signatures.
Distinguishing cancellation from close¶
Two sentinels to tell the cases apart:
v, err := q.RecvRawCtx(ctx, ch)
switch {
case errors.Is(err, q.ErrChanClosed):
// clean shutdown
case errors.Is(err, context.Canceled):
// someone asked us to stop
case errors.Is(err, context.DeadlineExceeded):
// we ran out of time
case err != nil:
// shouldn't happen — Raw only returns these three
}
See also¶
- q.Recv — no ctx, just the close-sentinel bubble
- q.CheckCtx — standalone ctx checkpoint, no channel
- q.AwaitCtx — same idea for
q.Future