chanctx

package module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 10, 2026 License: MIT Imports: 3 Imported by: 0

README

chanctx

Go's missing context.Context utilities channels.

Summary

Go's built-in channel operations are not context aware. In many codebases, I have seen the following operations deadlock or leak Goroutines:

Click to expand
// receive from a channel
val := <- ch

// send to a channel
ch <- val

// range over channel
for val := range ch {
	// ...
}

Ideally, the underlying channel would be closed when its underlying context.Context is closed, but this is easy to forget to do, or do incorrectly. Instead, it would be better if the channel operations themselves were context aware.

Thankfully, channel operations work with select, which is!

Click to expand
// receive from a channel
select {
case <- ctx.Done():
	// handle cancellation
case val, ok <- ch:
	// handle !ok
	// use val
}

// send to a channel
select {
case <- ctx.Done():
	// handle cancellation
case ch <- val:
	// value sent
}

// range over channel
for {
	select {
	case <- ctx.Done():
		// handle cancellation, usually break
	case val, ok <- ch:
		// handle !ok, usually break
		// use val
	}
}

However, all that selecting can easily make simple functions look complicated, and complicated functions look unreadable.

chanctx aims to bridge this gap: it provides a couple simple wrappers around these operations to make them more convenient to use:

Click to expand
// receive from a channel
val, err := chanctx.Receive(ctx, ch)
if err != nil {
	// the channel was closed, or context canceled
}

// send to a channel
if err := chanctx.Send(ctx, ch); err != nil {
	// context was cancelled
}

// range over channel
for val := range chanctx.IterReceive(ctx, ch) {
	// ...
}

Usage

Add it to your project:

go get github.com/Iron-E/chanctx@latest

Alternatively, since this project has zero dependencies, just copy chanctx.go into your project.

Documentation

Overview

Utils for safely doing chan operations that respect context.Context.

Use Send or Receive to send/receive on a channel, or IterReceive to range over a channel.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrContextCanceled = errors.New("context canceled")
	ErrChanClosed      = errors.New("channel closed")
)

Functions

func IterReceive

func IterReceive[T any](ctx context.Context, ch <-chan T) iter.Seq[T]

Yields all values received from a channel, and stops when either the context is cancelled, or the channel is empty and closed.

It is a safer alternative to:

for val := range ch { /* ... */ }

For context-sensitive operations.

func Receive

func Receive[T any](ctx context.Context, ch <-chan T) (val T, err error)

Try to receive a value from a channel.

Returns one of the following:

  • val, nil: if the value was received
  • *new(T), ErrContextCanceled: if the context is canceled
  • *new(T), ErrChanClosed: if there are no more values, and the channel is closed

In the case of ErrContextCanceled, the original ctx.Err() is preserved via errors.Join. Use errors.Is to detect it if necessary.

func Send

func Send[T any](ctx context.Context, ch chan<- T, val T) error

Try to send a value over a channel. Returns ErrContextCanceled if the context is cancelled.

In the case of ErrContextCanceled, the original ctx.Err() is preserved via errors.Join. Use errors.Is to detect it if necessary.

func TryReceive added in v1.1.0

func TryReceive[T any](ch <-chan T) (val T, ok bool)

Retrieve a value from the channel if there is one ready.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL