syncmap

package module
v0.0.0-...-8c9580d Latest Latest
Warning

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

Go to latest
Published: Jan 27, 2026 License: MIT Imports: 1 Imported by: 1

README

genericsyncmap

A typed, thread-safe map implementation for Go, built on top of sync.Map using generics.

genericsyncmap provides the concurrency benefits of sync.Map with the safety and convenience of Go generics. It implements the full feature set of sync.Map (as of Go 1.20+), and is as close to a drop-in replacement as possible. You can remove the type casts from your code, and replace them with this.

Features

  • Type Safety: No more interface{} casting or assertions. Compile-time checks for key and value types.
  • Thread Safety: Fully safe for concurrent use by multiple goroutines without additional locking.
  • Full Parity: Implements all methods found in the standard library's sync.Map.
  • Zero Dependencies: Built strictly on the standard library.

Installation

go get github.com/donomii/genericsyncmap

Use

Basic Operations
package main

import (
	"fmt"
	"github.com/donomii/genericsyncmap"
)

func main() {
	// Create a new map with string keys and int values
	m := syncmap.NewSyncMap[string, int]()

	// Store values
	m.Store("apple", 10)
	m.Store("banana", 20)

	// Load values
	if val, ok := m.Load("apple"); ok {
		fmt.Printf("Apple count: %d\n", val)
	}

	// Delete
	m.Delete("banana")
}
Atomic Operations

One of the main advantages of sync.Map is the ability to perform atomic operations without external locks. genericsyncmap exposes all of these in a type-safe way:

// LoadOrStore
val, loaded := m.LoadOrStore("cherry", 5)

// LoadAndDelete
val, loaded = m.LoadAndDelete("apple")

// Swap (Store and return previous)
prev, loaded := m.Swap("grape", 30)

// CompareAndSwap (Swap only if old value matches)
swapped := m.CompareAndSwap("grape", 30, 35)

// CompareAndDelete (Delete only if value matches)
deleted := m.CompareAndDelete("grape", 35)
Iteration

Use the Range method to iterate over the map. Returning false from the callback stops iteration.

m.Range(func(key string, value int) bool {
    fmt.Printf("%s: %d\n", key, value)
    return true // continue iteration
})

Helper methods Keys(), Values(), and Len() are also provided, though be aware that Len() requires iterating the entire map (O(N)).

Performance

Since this is a thin wrapper around sync.Map, performance characteristics are identical:

  • Optimized for cases where keys are stable (loaded/read often, updated rarely).
  • Excellent for cache implementations.

Benchmarks included in the repository (go test -bench .).

License

MIT

Documentation

Overview

A typed, thread-safe map built on top of sync.Map, using generics.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type SyncMap

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

SyncMap provides a thread-safe generic map built on top of sync.Map.

Example (Range)

ExampleSyncMap_range demonstrates how to iterate over the map

package main

import (
	"fmt"
	"sort"

	syncmap "github.com/donomii/genericsyncmap"
)

func main() {
	m := syncmap.NewSyncMap[string, string]()
	m.Store("LOC", "USA")
	m.Store("LANG", "EN")

	// Collect keys for consistent output order
	var keys []string
	m.Range(func(key string, value string) bool {
		keys = append(keys, key)
		return true
	})
	sort.Strings(keys)

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

}
Output:
LANG: EN
LOC: USA
Example (Usage)

ExampleSyncMap_usage demonstrates basic usage of SyncMap

package main

import (
	"fmt"

	syncmap "github.com/donomii/genericsyncmap"
)

func main() {
	m := syncmap.NewSyncMap[string, int]()

	m.Store("apple", 10)
	m.Store("banana", 20)

	if val, ok := m.Load("apple"); ok {
		fmt.Printf("apple: %d\n", val)
	}

	m.Delete("banana")

}
Output:
apple: 10

func NewSyncMap

func NewSyncMap[K comparable, V any]() *SyncMap[K, V]

NewSyncMap creates a new thread-safe generic map

func (*SyncMap[K, V]) CompareAndDelete

func (sm *SyncMap[K, V]) CompareAndDelete(key K, old V) (deleted bool)

CompareAndDelete deletes the entry for key if its value is equal to old. The old value must be of a comparable type.

func (*SyncMap[K, V]) CompareAndSwap

func (sm *SyncMap[K, V]) CompareAndSwap(key K, old V, new V) (swapped bool)

CompareAndSwap swaps the old and new values for key if the value stored in the map is equal to old. The old value must be of a comparable type.

func (*SyncMap[K, V]) Delete

func (sm *SyncMap[K, V]) Delete(key K)

Delete removes a key

func (*SyncMap[K, V]) Keys

func (sm *SyncMap[K, V]) Keys() []K

Keys returns all keys as a slice

func (*SyncMap[K, V]) Len

func (sm *SyncMap[K, V]) Len() int

Len returns the number of items (expensive operation)

func (*SyncMap[K, V]) Load

func (sm *SyncMap[K, V]) Load(key K) (V, bool)

Load gets a value by key, returns value and whether it was found

func (*SyncMap[K, V]) LoadAndDelete

func (sm *SyncMap[K, V]) LoadAndDelete(key K) (V, bool)

LoadAndDelete gets existing value and deletes it, returns value and whether it was loaded (deleted)

func (*SyncMap[K, V]) LoadOrStore

func (sm *SyncMap[K, V]) LoadOrStore(key K, value V) (V, bool)

LoadOrStore gets existing value or stores new one, returns actual value and whether it was loaded

func (*SyncMap[K, V]) Range

func (sm *SyncMap[K, V]) Range(fn func(key K, value V) bool)

Range calls fn for each key-value pair. Returning false quits the iteration

func (*SyncMap[K, V]) Store

func (sm *SyncMap[K, V]) Store(key K, value V)

Store sets a key-value pair

func (*SyncMap[K, V]) Swap

func (sm *SyncMap[K, V]) Swap(key K, value V) (previous V, loaded bool)

Swap swaps the value for a key and returns the previous value if any. The loaded result reports whether the key was present.

func (*SyncMap[K, V]) Values

func (sm *SyncMap[K, V]) Values() []V

Values returns all values as a slice

Jump to

Keyboard shortcuts

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