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.
- 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.
go get github.com/donomii/genericsyncmappackage 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")
}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)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)).
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 .).
MIT