Skip to content

Channel

A generic, telemetry-aware channel wrapper. Provides observable Send and Receive operations with opt-in/out metrics and tracing.

Lives in the github.com/foomo/gofuncy/channel subpackage.

Signature

go
func New[T any](opts ...Option[T]) *Channel[T]

Type Parameters

ParameterDescription
TThe type of values sent through the channel.

Parameters

ParameterTypeDescription
opts...Option[T]Functional options to configure the channel.

Options

Defaults

FeatureDefaultOption
Name"gofuncy.channel"WithName[T](name)
Buffer size0 (unbuffered)WithBuffer[T](size)
Loggerslog.Default()WithLogger[T](l)
Chans counter (gofuncy.chans.current)onWithoutChansCounter[T]()
Messages sent counter (gofuncy.messages.sent)onWithoutMessagesSentCounter[T]()
Duration histogram (gofuncy.messages.duration.seconds)offWithDurationHistogram[T]()
TracingoffWithTracing[T]()
Meter providerOTel globalWithMeterProvider[T](mp)
Tracer providerOTel globalWithTracerProvider[T](tp)

TIP

Counters are cheap and enabled by default. Duration histogram and tracing are opt-in because they add overhead on every Send call. This matches the convention used by Go, Do, Wait, and Group.

Behavior

  1. New creates the underlying Go channel and initializes telemetry instruments based on the enabled options.
  2. If the chans counter is enabled, the channel increments gofuncy.chans.current on creation and decrements it on Close.
  3. Send writes values to the channel one at a time. For each value:
    • If the context is cancelled, returns the context error immediately.
    • If the channel is closed, returns channel.ErrClosed.
    • If the messages sent counter is enabled, increments gofuncy.messages.sent.
    • If the duration histogram is enabled, records the time spent waiting for the channel to accept the value (backpressure detection).
    • If tracing is enabled, adds a span event for each sent value.
  4. Receive returns the raw underlying <-chan T. This is zero-allocation and works with range.
  5. Close is idempotent — safe to call multiple times. It broadcasts to all blocked senders, then closes the underlying channel.

Methods

Send

go
func (c *Channel[T]) Send(ctx context.Context, values ...T) error

Sends one or more values into the channel. Returns channel.ErrClosed if the channel has been closed, or the context error if the context is cancelled while waiting.

Receive

go
func (c *Channel[T]) Receive() <-chan T

Returns a read-only view of the underlying channel. Use with range or select.

Close

go
func (c *Channel[T]) Close()

Closes the channel. Idempotent — subsequent calls are no-ops. Unblocks any goroutines waiting in Send.

Len / Cap / Name

go
func (c *Channel[T]) Len() int
func (c *Channel[T]) Cap() int
func (c *Channel[T]) Name() string

Return the current number of buffered values, the buffer capacity, and the channel name.

Example

go
package main

import (
	"context"
	"fmt"
	"time"

	"github.com/foomo/gofuncy"
	"github.com/foomo/gofuncy/channel"
)

func main() {
	ctx := context.Background()

	// Create a buffered channel with default telemetry (counters on)
	ch := channel.New[string](channel.WithBuffer[string](10))

	// Producer
	gofuncy.Go(ctx, func(ctx context.Context) error {
		defer ch.Close()

		for i := range 5 {
			if err := ch.Send(ctx, fmt.Sprintf("event-%d", i)); err != nil {
				return err
			}
		}

		return nil
	})

	// Consumer
	for msg := range ch.Receive() {
		fmt.Println(msg)
	}

	time.Sleep(100 * time.Millisecond)
}

Telemetry Metrics

MetricTypeDescription
gofuncy.chans.currentUpDownCounterNumber of open channels. Attributes: gofuncy.chan.name, gofuncy.chan.cap.
gofuncy.messages.sentCounterTotal messages sent. Attributes: gofuncy.chan.name.
gofuncy.messages.duration.secondsHistogramTime spent waiting for the channel to accept a value. High values indicate backpressure. Attributes: gofuncy.chan.name.

WARNING

Receive() returns the raw Go channel. The gofuncy.messages.sent counter tracks total sends only — it is not decremented on receive. To detect stuck or filling channels, compare the sent counter growth over time or use the duration histogram to measure backpressure.