dchan

package
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Apr 30, 2026 License: Apache-2.0, MIT Imports: 2 Imported by: 0

README

dchan

dchan is a Go library that provides a dynamic channel with unlimited capacity and additional features for more efficient data operations.

Functions

  • New[T any](params ...any) *C[T]: Initializes a new channel.
  • Send(data T): Sends a value to the channel.
  • Receive() (T, bool): Retrieves a value from the channel.
  • Close(f ...func(T)) : Closes the channel; optionally accepts a function to handle any remaining values or nil to discard them.
  • Ready(f func(T) bool) bool: Checks if the first element in the channel is ready for retrieval based on a custom boolean function, without actually removing it from the channel (available only in SliceMode).
  • Len() int : Returns the current length of the channel.
  • IsClosed() bool: Checks whether the channel is closed.

Usage

Creating a new channel ([T any])
ch := dchan.New[int64]()
// ch := dchan.New[*MyStruct]()

By default, the initial capacity is set to 1024 values, with storage implemented as a slice of Go channels that automatically expands as it fills. The behavior closely mirrors that of standard Go channels.

Additional configuration options:

ch := dchan.New[int](10240) // type *dchan.C
// ch := dchan.New[int](dchan.Relaxed)
// ch := dchan.New[int](10240, dchan.Relaxed)
  • 10240 - Initial capacity for storing up to 10,240 values (automatically expanding as it fills).
  • flag dchan.SliceMode - will use slices for storage.
  • flag dchan.Relaxed - Permits sending to a closed channel and closing the channel multiple times without causing a panic. Note that while correct uses of dchan.Relaxed do exist, they are rare, and use of dchan.Relaxed is often a sign of a deeper problem in the program's logic.
Sending and receiving values
ch.Send(1)
val, ok := ch.Receive()

Iterating over channel values
// Equivalent to standard channel reading: for val := range ch { ... }
for val,ok := ch.Receive(); ok; val,ok = ch.Receive() {
    // process val
}
Closing the channel
ch.Close()
// ch.Close(f)
// ch.Close(nil)

Extra parameters are: func(T) or nil.

  • ch.Close(func(T)) - function to process (or utilize) elements remaining in the channel.
  • ch.Close(nil) - discards any remaining elements in the channel.
Determines if the first element in the channel is ready (SliceMode only)
ready := ch.Ready(func(v T) bool { return v.Status == READY })

// func readyFunc(v int) bool {
// 	return v == 10
// }
// ...
// if ch.Ready(readyFunc) {
//     ...
// }
Getting the length of the channel
length := ch.Len()
Checking whether the channel is closed.
closed := ch.IsClosed()
A basic example:
package main

import (
	"fmt"
	"time"

	"github.com/hitsumitomo/dchan"
)

func utilizeFunc(i int) {
	fmt.Printf("Utilize: %v\n", i)
}

func main() {
	ch := dchan.New[int]()

	// Method1 (Equivalent to standard channel reading: for val := range ch { ... })
	go func() {
		i := 0
		for val, ok := ch.Receive(); ok; val, ok = ch.Receive() {
			fmt.Println("Method1:", val)
			if i++; i == 4 {
				break
			}
		}
	}()

	// Method2
	go func() {
		i := 0
		for {
			val, ok := ch.Receive()
			if !ok {
				break
			}
			fmt.Println("Method2:", val)
			if i++; i == 4 {
				break
			}
		}
	}()

	for i := 0; i < 10; i++ {
		ch.Send(i)
	}

	time.Sleep(time.Second)
	ch.Close(utilizeFunc)
	time.Sleep(time.Second)

	fmt.Println()
	// ------------------------------
	ch = dchan.New[int](dchan.SliceMode | dchan.Relaxed)
	// also allowed:
	// ch = dchan.New[int64](2048)
	// ch = dchan.New[int64](2048, dchan.Relaxed)

	go func() {
		for val, ok := ch.Receive(); ok; val, ok = ch.Receive() {
			fmt.Println("Method3:", val)
		}
		fmt.Println("Channel is closed")
	}()

	for i := 0; i < 5; i++ {
		ch.Send(i)
	}

	time.Sleep(time.Second)
	ch.Close()
	ch.Send(100)
	ch.Close()
	time.Sleep(time.Second)
}

// Method1: 0
// Method1: 2
// Method1: 3
// Method1: 4
// Method2: 1
// Method2: 5
// Method2: 6
// Method2: 7
// Utilize: 8
// Utilize: 9

// Method3: 0
// Method3: 1
// Method3: 2
// Method3: 3
// Method3: 4
// Channel is closed
Benchmarks
BenchmarkDchanSend-4                    1000000000        0.06726 ns/op    0 B/op     0 allocs/op
BenchmarkDchanReceive-4                 1000000000        0.06754 ns/op    0 B/op     0 allocs/op
BenchmarkDchanConcurrent-4                 6965311      172.7 ns/op        9 B/op     0 allocs/op
BenchmarkDchanSliceModeSend-4           1000000000        0.03978 ns/op    0 B/op     0 allocs/op
BenchmarkDchanSliceModeReceive-4        1000000000        0.02774 ns/op    0 B/op     0 allocs/op
BenchmarkDchanSliceModeConcurrent-4       11675958      125.3 ns/op       16 B/op     0 allocs/op
BenchmarkChannelSend-4                  1000000000        0.03446 ns/op    0 B/op     0 allocs/op
BenchmarkChannelReceive-4               1000000000        0.03369 ns/op    0 B/op     0 allocs/op
BenchmarkChannelConcurrent-4               3614706      328.8 ns/op        0 B/op     0 allocs/op

Documentation

Index

Constants

View Source
const (
	// Strict mode will panic on send on a closed channel.
	Strict = byte(0b00000001)
	// Relaxed mode will ignore send on a closed channel.
	Relaxed = byte(0b00000010)
	// SliceMode will use slices for storage.
	SliceMode = byte(0b00000100)
)

Variables

This section is empty.

Functions

This section is empty.

Types

type C

type C[T any] struct {
	// contains filtered or unexported fields
}

C is a dynamically growing channel.

func New

func New[T any](params ...any) *C[T]

New creates a new dynamic channel.

func (*C[T]) Close

func (c *C[T]) Close(f ...func(T))

Close closes the dynamic channel. If function is provided, it will be be executed for each remaining item in the channel. If nil is provided, the items will be discarded.

func (*C[T]) IsClosed

func (c *C[T]) IsClosed() bool

IsClosed checks if the dynamic channel is closed.

func (*C[T]) Len

func (c *C[T]) Len() int

Len returns the number of items in the dynamic channel.

func (*C[T]) Ready

func (c *C[T]) Ready(f func(T) bool) bool

Ready checks if item is ready for extraction. Note: works only with sliceMode mode.

func (*C[T]) Receive

func (c *C[T]) Receive() (T, bool)

Receive retrieves an item from the dynamic channel. It returns the item and a boolean indicating whether the retrieval was successful.

func (*C[T]) Send

func (c *C[T]) Send(data T)

Send adds an item to the dynamic channel.

Jump to

Keyboard shortcuts

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