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 ¶
- type Chan
- type Map
- func (m *Map[K, V]) All() iter.Seq2[K, V]
- func (m *Map[K, V]) CheckGet(key K) (V, bool)
- func (m *Map[K, V]) Clear()
- func (m *Map[K, V]) Delete(key K)
- func (m *Map[K, V]) Get(key K) V
- func (m *Map[K, V]) Keys() iter.Seq[K]
- func (m *Map[K, V]) Len() int
- func (m *Map[K, V]) Map() map[K]V
- func (m *Map[K, V]) Set(key K, value V)
- func (m *Map[K, V]) Values() iter.Seq[V]
- type OnceValue
- type OnceValues
- type Slice
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
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
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
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 ¶
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
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
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 ¶
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.
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!
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