Skip to content

donomii/genericsyncmap

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

genericsyncmap

CI codecov Go Reference Go Report Card License

genericsyncmap is a type-safe generic wrapper for Go's sync.Map. It provides the full Go 1.24 sync.Map API without caller-side type assertions, plus typed iteration and collection helpers.

Features

  • Type-safe keys and values
  • Safe concurrent access without external locking
  • Full method parity with Go 1.24's sync.Map
  • All, Keys, Values, and Len helpers
  • Zero dependencies outside the standard library

Installation

go get github.com/donomii/genericsyncmap

Go 1.24 or newer is required.

Use

The zero value of Map is ready for use:

package main

import (
	"fmt"

	"github.com/donomii/genericsyncmap"
)

func main() {
	var m syncmap.Map[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")
	m.Clear()
}

SyncMap[K, V] remains an alias for Map[K, V], and NewSyncMap[K, V]() remains available for compatibility. Like sync.Map, a Map must not be copied after first use.

Atomic Operations

val, loaded := m.LoadOrStore("cherry", 5)
val, loaded = m.LoadAndDelete("apple")
prev, loaded := m.Swap("grape", 30)
swapped := m.CompareAndSwap("grape", 30, 35)
deleted := m.CompareAndDelete("grape", 35)

CompareAndSwap and CompareAndDelete require the old value to be comparable, matching sync.Map behavior. They panic if given a non-comparable old value.

Iteration

Use All with Go's range-over-function syntax:

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

Range is also available. Returning false stops iteration:

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

All and Range do not necessarily observe a consistent snapshot if the map is modified concurrently. Keys, Values, and Len inherit that behavior. Len iterates over the entire map in O(N) time.

Performance

The benchmarks compare genericsyncmap.Map, raw sync.Map, and a built-in map protected by sync.RWMutex. All mixed-workload maps are prepopulated with 1,024 keys, and operations and keys are selected independently.

Results from Go 1.26.2 on an Apple M5 Pro (darwin/arm64):

Benchmark genericsyncmap sync.Map map + RWMutex
Load hit 5.18 ns/op 4.68 ns/op 3.78 ns/op
Store existing 26.4 ns/op 24.8 ns/op 8.00 ns/op
Concurrent 50/50 load/store 19.4 ns/op 20.6 ns/op 74.2 ns/op

These results are a single-machine measurement, not a performance guarantee. Run the benchmarks for the workload and hardware that matter to you:

go test -bench . -benchmem

Like sync.Map, this package is optimized for workloads where entries are written once and read many times, or where goroutines access disjoint key sets.

License

MIT

About

Type-safe generic wrapper for Go’s sync.Map with full API parity and zero dependencies.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages