safemap API

safemap

package

API reference for the safemap package.

S
struct

Map

Map is a generic thread-safe map.

It uses a sync.RWMutex to guard access to the underlying map.

pkg/safemap/map.go:13-16
type Map struct

Example

m := safemap.New[string, int]()
m.Set("key", 42)

Fields

Name Type Description
data map[K]V
mu sync.RWMutex
F
function

New

New creates a new empty SafeMap.

Returns

*Map[K,
V]
pkg/safemap/map.go:19-23
func New[K comparable, V any]() *Map[K, V]

{
	return &Map[K, V]{
		data: make(map[K]V),
	}
}
F
function

TestMap_Basic

Parameters

pkg/safemap/map_test.go:8-29
func TestMap_Basic(t *testing.T)

{
	m := New[string, int]()

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

	if v, ok := m.Get("a"); !ok || v != 1 {
		t.Errorf("Get a: got %d, want 1", v)
	}

	if !m.Has("b") {
		t.Error("Has b: should be true")
	}

	if m.Has("c") {
		t.Error("Has c: should be false")
	}

	if m.Len() != 2 {
		t.Errorf("Len: got %d, want 2", m.Len())
	}
}
F
function

TestMap_Delete

Parameters

pkg/safemap/map_test.go:31-39
func TestMap_Delete(t *testing.T)

{
	m := New[string, string]()
	m.Set("key", "value")
	m.Delete("key")

	if m.Has("key") {
		t.Error("key should be deleted")
	}
}
F
function

TestMap_Clear

Parameters

pkg/safemap/map_test.go:41-50
func TestMap_Clear(t *testing.T)

{
	m := New[int, int]()
	m.Set(1, 100)
	m.Set(2, 200)
	m.Clear()

	if m.Len() != 0 {
		t.Errorf("Clear: Len should be 0, got %d", m.Len())
	}
}
F
function

TestMap_Keys

Parameters

pkg/safemap/map_test.go:52-61
func TestMap_Keys(t *testing.T)

{
	m := New[string, int]()
	m.Set("x", 1)
	m.Set("y", 2)

	keys := m.Keys()
	if len(keys) != 2 {
		t.Errorf("Keys: got %d, want 2", len(keys))
	}
}
F
function

TestMap_Values

Parameters

pkg/safemap/map_test.go:63-72
func TestMap_Values(t *testing.T)

{
	m := New[string, int]()
	m.Set("x", 10)
	m.Set("y", 20)

	vals := m.Values()
	if len(vals) != 2 {
		t.Errorf("Values: got %d, want 2", len(vals))
	}
}
F
function

TestMap_Range

Parameters

pkg/safemap/map_test.go:74-89
func TestMap_Range(t *testing.T)

{
	m := New[string, int]()
	m.Set("a", 1)
	m.Set("b", 2)
	m.Set("c", 3)

	count := 0
	m.Range(func(k string, v int) bool {
		count++
		return count < 2
	})

	if count != 2 {
		t.Errorf("Range should stop early, got %d iterations", count)
	}
}
F
function

TestMap_GetOrSet

Parameters

pkg/safemap/map_test.go:91-103
func TestMap_GetOrSet(t *testing.T)

{
	m := New[string, int]()

	v1 := m.GetOrSet("key", 42)
	if v1 != 42 {
		t.Errorf("GetOrSet first call: got %d, want 42", v1)
	}

	v2 := m.GetOrSet("key", 100)
	if v2 != 42 {
		t.Errorf("GetOrSet second call: got %d, want 42", v2)
	}
}
F
function

TestMap_Compute

Parameters

pkg/safemap/map_test.go:105-123
func TestMap_Compute(t *testing.T)

{
	m := New[string, int]()

	m.Compute("counter", func(v int, exists bool) int {
		return v + 1
	})

	if v, _ := m.Get("counter"); v != 1 {
		t.Errorf("Compute first: got %d, want 1", v)
	}

	m.Compute("counter", func(v int, exists bool) int {
		return v + 1
	})

	if v, _ := m.Get("counter"); v != 2 {
		t.Errorf("Compute second: got %d, want 2", v)
	}
}
F
function

TestMap_Concurrent

Parameters

pkg/safemap/map_test.go:125-144
func TestMap_Concurrent(t *testing.T)

{
	m := New[int, int]()
	var wg sync.WaitGroup

	for i := 0; i < 100; i++ {
		wg.Add(1)
		go func(n int) {
			defer wg.Done()
			m.Set(n, n*10)
			m.Get(n)
			m.Has(n)
		}(i)
	}

	wg.Wait()

	if m.Len() != 100 {
		t.Errorf("Concurrent: got %d items, want 100", m.Len())
	}
}