zeros

package module
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Jul 12, 2026 License: BSD-3-Clause Imports: 2 Imported by: 2

Documentation

Overview

Package zeros provides zero-valueable wrappers for channels, maps, slices, and sync.OnceValues.

Chan and Map auto-initialize their underlying types on first use, allowing them to be used without explicit initialization. Initialization is thread-safe, but the types themselves are not safe for concurrent access without external synchronization (like Go's built-in map type).

Slice is a slice type whose Append method mutates in place and returns the updated slice, letting package-level var initializers across files append to a single value.

OnceValue and OnceValues provide zero-valueable alternatives to sync.OnceValue and sync.OnceValues, allowing them to be used as struct fields without initialization.

Example usage:

var ch zeros.Chan[int]
ch.Send(42)  // auto-initializes the channel
v := ch.Recv()

var m zeros.Map[string, int]
m.Set("answer", 42)  // auto-initializes the map
v, ok := m.Get("answer")

for k, v := range m.All() {
	fmt.Printf("%s: %d\n", k, v)
}

var s zeros.Slice[int]
var _ = s.Append(1)  // works across package-level initializers
var _ = s.Append(2, 3)

type Config struct {
	value zeros.OnceValue[int]
}
result := config.value.Do(func() int { return 42 })

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Chan

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

Chan is a zero-valueable channel wrapper that auto-initializes on first use.

Example
package main

import (
	"fmt"

	"lesiw.io/zeros"
)

func main() {
	var ch zeros.Chan[int]

	go func() {
		ch.Send(42)
	}()

	v := ch.Recv()
	fmt.Println(v)
}
Output:
42

func (*Chan[T]) Chan added in v0.2.0

func (c *Chan[T]) Chan() chan T

Chan returns the underlying channel.

func (*Chan[T]) CheckRecv added in v0.2.0

func (c *Chan[T]) CheckRecv() (T, bool)

CheckRecv receives a value from the channel with a status indicator. The boolean return value indicates whether the channel is open.

Example
package main

import (
	"fmt"

	"lesiw.io/zeros"
)

func main() {
	var ch zeros.Chan[int]

	go func() {
		ch.Send(100)
		ch.Close()
	}()

	if v, ok := ch.CheckRecv(); ok {
		fmt.Println("received:", v)
	}

	if _, ok := ch.CheckRecv(); !ok {
		fmt.Println("channel closed")
	}
}
Output:
received: 100
channel closed

func (*Chan[T]) Close

func (c *Chan[T]) Close()

Close closes the underlying channel.

Example
package main

import (
	"fmt"

	"lesiw.io/zeros"
)

func main() {
	var ch zeros.Chan[string]

	go func() {
		ch.Send("hello")
		ch.Close()
	}()

	for {
		msg, ok := ch.CheckRecv()
		if !ok {
			break
		}
		fmt.Println(msg)
	}
}
Output:
hello

func (*Chan[T]) Recv added in v0.2.0

func (c *Chan[T]) Recv() T

Recv receives a value from the channel, blocking until a value is available. Returns the zero value if the channel is closed.

func (*Chan[T]) Send added in v0.2.0

func (c *Chan[T]) Send(v T)

Send sends a value on the channel, blocking until the value is sent.

func (*Chan[T]) TryRecv added in v0.2.0

func (c *Chan[T]) TryRecv() (T, bool)

TryRecv attempts to receive a value from the channel without blocking. If a value is available, it returns the value and true. If no value is available, it returns the zero value and false. If the channel is closed, it returns the zero value and false.

Example
package main

import (
	"fmt"

	"lesiw.io/zeros"
)

func main() {
	var ch zeros.Chan[int]

	// TryRecv returns false if no value is available
	if _, ok := ch.TryRecv(); !ok {
		fmt.Println("no value available")
	}
}
Output:
no value available

func (*Chan[T]) TrySend added in v0.2.0

func (c *Chan[T]) TrySend(v T) bool

TrySend attempts to send a value on the channel without blocking. It reports whether the value was sent.

Example
package main

import (
	"fmt"

	"lesiw.io/zeros"
)

func main() {
	var ch zeros.Chan[int]

	// TrySend returns false if no receiver is ready
	if !ch.TrySend(42) {
		fmt.Println("no receiver ready")
	}
}
Output:
no receiver ready

type Map

type Map[K comparable, V any] struct {
	// contains filtered or unexported fields
}

Map is a zero-valueable map wrapper that auto-initializes on first use.

Example
package main

import (
	"fmt"

	"lesiw.io/zeros"
)

func main() {
	var m zeros.Map[string, int]

	m.Set("answer", 42)

	if v, ok := m.CheckGet("answer"); ok {
		fmt.Println(v)
	}
}
Output:
42

func (*Map[K, V]) All

func (m *Map[K, V]) All() iter.Seq2[K, V]

All returns an iterator over key-value pairs in the map.

Example
package main

import (
	"fmt"

	"lesiw.io/zeros"
)

func main() {
	var m zeros.Map[string, string]

	m.Set("hello", "world")
	m.Set("foo", "bar")

	for k, v := range m.All() {
		fmt.Println(k, v)
	}
}
Output:
hello world
foo bar

func (*Map[K, V]) CheckGet added in v0.2.0

func (m *Map[K, V]) CheckGet(key K) (V, bool)

CheckGet retrieves a value by key with a presence indicator.

Example
package main

import (
	"fmt"

	"lesiw.io/zeros"
)

func main() {
	var m zeros.Map[string, int]

	m.Set("exists", 100)

	if v, ok := m.CheckGet("exists"); ok {
		fmt.Println("found:", v)
	}

	if _, ok := m.CheckGet("missing"); !ok {
		fmt.Println("not found")
	}
}
Output:
found: 100
not found

func (*Map[K, V]) Clear

func (m *Map[K, V]) Clear()

Clear removes all elements from the map.

Example
package main

import (
	"fmt"

	"lesiw.io/zeros"
)

func main() {
	var m zeros.Map[string, int]

	m.Set("a", 1)
	m.Set("b", 2)
	fmt.Println(m.Len())

	m.Clear()
	fmt.Println(m.Len())
}
Output:
2
0

func (*Map[K, V]) Delete

func (m *Map[K, V]) Delete(key K)

Delete removes a key.

Example
package main

import (
	"fmt"

	"lesiw.io/zeros"
)

func main() {
	var m zeros.Map[string, int]

	m.Set("key", 100)
	fmt.Println(m.Len())

	m.Delete("key")
	fmt.Println(m.Len())
}
Output:
1
0

func (*Map[K, V]) Get

func (m *Map[K, V]) Get(key K) V

Get retrieves a value by key, returning the zero value if not found.

Example
package main

import (
	"fmt"

	"lesiw.io/zeros"
)

func main() {
	var m zeros.Map[string, int]

	m.Set("exists", 100)

	fmt.Println(m.Get("exists"))
	fmt.Println(m.Get("missing"))
}
Output:
100
0

func (*Map[K, V]) Keys added in v0.2.0

func (m *Map[K, V]) Keys() iter.Seq[K]

Keys returns an iterator over keys in the map.

Example
package main

import (
	"fmt"

	"lesiw.io/zeros"
)

func main() {
	var m zeros.Map[string, int]

	m.Set("a", 1)
	m.Set("b", 2)

	for k := range m.Keys() {
		fmt.Println(k)
	}
}
Output:
a
b

func (*Map[K, V]) Len

func (m *Map[K, V]) Len() int

Len returns the number of elements.

Example
package main

import (
	"fmt"

	"lesiw.io/zeros"
)

func main() {
	var m zeros.Map[string, int]

	fmt.Println(m.Len())

	m.Set("a", 1)
	m.Set("b", 2)

	fmt.Println(m.Len())
}
Output:
0
2

func (*Map[K, V]) Map added in v0.2.0

func (m *Map[K, V]) Map() map[K]V

Map returns the underlying map.

func (*Map[K, V]) Set

func (m *Map[K, V]) Set(key K, value V)

Set sets a key-value pair.

func (*Map[K, V]) Values added in v0.2.0

func (m *Map[K, V]) Values() iter.Seq[V]

Values returns an iterator over values in the map.

Example
package main

import (
	"fmt"

	"lesiw.io/zeros"
)

func main() {
	var m zeros.Map[string, int]

	m.Set("a", 1)
	m.Set("b", 2)

	for v := range m.Values() {
		fmt.Println(v)
	}
}
Output:
1
2

type OnceValue added in v0.3.0

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

OnceValue is a zero-valueable wrapper that executes and caches the result of a function on first call.

Unlike sync.OnceValue which returns a function, OnceValue is a struct type that can be used as a zero-value field in other structs.

If f panics, Do will panic with the same value on every call.

Example
package main

import (
	"fmt"

	"lesiw.io/zeros"
)

func main() {
	type lazyReader struct {
		init zeros.OnceValue[string]
	}
	var r lazyReader

	data := r.init.Do(func() string {
		fmt.Println("Loading data")
		return "Hello, World!"
	})
	fmt.Println(data)

	data = r.init.Do(func() string {
		fmt.Println("This won't print")
		return "Goodbye"
	})
	fmt.Println(data)

}
Output:
Loading data
Hello, World!
Hello, World!

func (*OnceValue[T]) Do added in v0.3.0

func (o *OnceValue[T]) Do(f func() T) T

Do calls f and caches its return value on the first call. Subsequent calls return the cached value without calling f.

If f panics, Do will panic with the same value on every call.

type OnceValues added in v0.3.0

type OnceValues[T1, T2 any] struct {
	// contains filtered or unexported fields
}

OnceValues is a zero-valueable wrapper that executes and caches the results of a function on first call.

Unlike sync.OnceValues which returns a function, OnceValues is a struct type that can be used as a zero-value field in other structs.

If f panics, Do will panic with the same value on every call.

Example
package main

import (
	"fmt"
	"io"
	"os"

	"lesiw.io/zeros"
)

type lazyFile struct {
	once zeros.OnceValues[*os.File, error]
}

func (f *lazyFile) init() (*os.File, error) {
	fmt.Println("Creating temp file")
	return os.CreateTemp("", "example")
}

func (f *lazyFile) Write(p []byte) (int, error) {
	file, err := f.once.Do(f.init)
	if err != nil {
		return 0, fmt.Errorf("failed to open file: %w", err)
	}
	return file.Write(p)
}

func (f *lazyFile) Close() error {
	file, err := f.once.Do(f.init)
	if err != nil {
		return fmt.Errorf("failed to close file: %w", err)
	}
	defer os.Remove(file.Name())
	return file.Close()
}

func (f *lazyFile) Stat() (os.FileInfo, error) {
	file, err := f.once.Do(f.init)
	if err != nil {
		return nil, fmt.Errorf("failed to stat file: %w", err)
	}
	return file.Stat()
}

func main() {
	var f lazyFile
	defer f.Close()

	info, err := f.Stat()
	if err != nil {
		fmt.Printf("Stat failed: %v\n", err)
		return
	}
	fmt.Printf("Initial size: %d bytes\n", info.Size())

	if _, err := io.WriteString(&f, "Hello, world!"); err != nil {
		fmt.Printf("Copy failed: %v\n", err)
		return
	}

	info, err = f.Stat()
	if err != nil {
		fmt.Printf("Stat failed: %v\n", err)
		return
	}
	fmt.Printf("Final size: %d bytes\n", info.Size())

}
Output:
Creating temp file
Initial size: 0 bytes
Final size: 13 bytes

func (*OnceValues[T1, T2]) Do added in v0.3.0

func (o *OnceValues[T1, T2]) Do(f func() (T1, T2)) (T1, T2)

Do calls f and caches its return values on the first call. Subsequent calls return the cached values without calling f.

If f panics, Do will panic with the same value on every call.

type Slice added in v0.4.0

type Slice[T any] []T

Slice is a zero-valueable slice type whose Append method mutates in place and returns the updated slice.

Example
package main

import (
	"fmt"

	"lesiw.io/zeros"
)

func main() {
	var s zeros.Slice[int]

	s.Append(1)
	s.Append(2, 3)

	for _, v := range s {
		fmt.Println(v)
	}
}
Output:
1
2
3

func (*Slice[T]) Append added in v0.4.0

func (s *Slice[T]) Append(v ...T) Slice[T]

Append appends values in place and returns the updated slice.

Jump to

Keyboard shortcuts

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