gsyncmap

package module
v0.4.1 Latest Latest
Warning

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

Go to latest
Published: Jun 22, 2026 License: MIT Imports: 1 Imported by: 0

README

Generic Sync Map

Go Reference codecov

English | 繁體中文

A generic, type-safe wrapper around sync.Map for Go.

Features

  • Type-safe — keys and values are statically typed; no any casts at call sites.
  • Zero-value ready — the zero value is usable immediately, just like sync.Map.
  • Familiar API — mirrors the standard sync.Map method set.
  • No dependencies — built entirely on the standard library.

Installation

go get github.com/min0625/gsyncmap

Requires Go 1.24 or later.

Types

Type Value constraint CompareAndDelete / CompareAndSwap
Map[Key comparable, Value any] any available but deprecated (may panic at runtime)
ComparableMap[Key, Value comparable] comparable safe, panic-free
Map[Key comparable, Value any]

A generic concurrent map that accepts any value type. Suitable for most use cases.

Note: CompareAndDelete and CompareAndSwap are available on Map but deprecated — they panic at runtime if Value is not comparable (e.g. slice, map, func). Use ComparableMap when these operations are needed.

ComparableMap[Key, Value comparable]

A drop-in replacement for Map that requires the value type to be comparable. Provides safe CompareAndDelete and CompareAndSwap without risk of runtime panic.

Quick start

package main

import (
	"fmt"

	"github.com/min0625/gsyncmap"
)

func main() {
	var m gsyncmap.Map[string, string]

	m.Store("k1", "v1")
	fmt.Println(m.Load("k1")) // v1 true
	fmt.Println(m.Load("k2")) //  false

	m.Delete("k1")
	fmt.Println(m.Load("k1")) //  false
}

When CompareAndDelete or CompareAndSwap is needed, use ComparableMap:

package main

import (
	"fmt"

	"github.com/min0625/gsyncmap"
)

func main() {
	var m gsyncmap.ComparableMap[string, string]

	m.Store("k1", "v1")
	fmt.Println(m.CompareAndSwap("k1", "v1", "v2")) // true
	fmt.Println(m.Load("k1"))                       // v2 true
}

Documentation

License

See LICENSE.

Documentation

Overview

Package gsyncmap provides a generic, type-safe wrapper around sync.Map.

There are two map types available:

  • Map: accepts any value type. Suitable for most use cases. CompareAndDelete and CompareAndSwap are available but deprecated due to potential runtime panic when the value type is not comparable.

  • ComparableMap: requires the value type to implement comparable. Provides safe CompareAndDelete and CompareAndSwap without risk of panic.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ComparableMap added in v0.4.0

type ComparableMap[Key, Value comparable] struct {
	Map[Key, Value]
}

ComparableMap is a generic, type-safe concurrent map wrapping sync.Map.

ComparableMap is a drop-in replacement for Map when the value type is comparable. It overrides CompareAndDelete and CompareAndSwap with safe implementations that cannot panic, because the Value type constraint guarantees comparability at compile time.

The zero value of ComparableMap is valid and ready to use. ComparableMap must not be copied after first use (same restriction as sync.Map).

Example
package main

import (
	"fmt"

	"github.com/min0625/gsyncmap"
)

func main() {
	var m gsyncmap.ComparableMap[string, int]

	m.Store("k1", 1)
	fmt.Println(m.Load("k1"))

	// CompareAndSwap and CompareAndDelete are panic-free because the value
	// type is constrained to comparable.
	fmt.Println(m.CompareAndSwap("k1", 1, 2))
	fmt.Println(m.Load("k1"))
	fmt.Println(m.CompareAndDelete("k1", 2))
	fmt.Println(m.Load("k1"))

}
Output:
1 true
true
2 true
true
0 false

func (*ComparableMap[Key, Value]) CompareAndDelete added in v0.4.0

func (m *ComparableMap[Key, Value]) CompareAndDelete(key Key, oldVal Value) (deleted bool)

CompareAndDelete deletes the entry for key if its value is equal to oldVal. Returns true if the entry was deleted.

Example
package main

import (
	"fmt"

	"github.com/min0625/gsyncmap"
)

func main() {
	var m gsyncmap.ComparableMap[string, string]

	m.Store("k1", "v1")

	fmt.Println(m.Load("k1"))
	fmt.Println(m.CompareAndDelete("k1", "v2"))
	fmt.Println(m.CompareAndDelete("k1", "v1"))
	fmt.Println(m.Load("k1"))

}
Output:
v1 true
false
true
 false

func (*ComparableMap[Key, Value]) CompareAndSwap added in v0.4.0

func (m *ComparableMap[Key, Value]) CompareAndSwap(key Key, oldVal, newVal Value) (swapped bool)

CompareAndSwap swaps the oldVal and newVal values for key if the value stored in the map is equal to oldVal. Returns true if the swap was performed.

Example
package main

import (
	"fmt"

	"github.com/min0625/gsyncmap"
)

func main() {
	var m gsyncmap.ComparableMap[string, string]

	m.Store("k1", "a1")

	fmt.Println(m.Load("k1"))
	fmt.Println(m.CompareAndSwap("k1", "b1", "b2"))
	fmt.Println(m.Load("k1"))
	fmt.Println(m.CompareAndSwap("k1", "a1", "a2"))
	fmt.Println(m.Load("k1"))

}
Output:
a1 true
false
a1 true
true
a2 true

type Map

type Map[Key comparable, Value any] sync.Map

Map is a generic, type-safe concurrent map wrapping sync.Map.

The zero value of Map is valid and ready to use. Map must not be copied after first use (same restriction as sync.Map).

If the value type is known to be comparable and CompareAndDelete or CompareAndSwap is required, prefer using ComparableMap instead.

Example
package main

import (
	"fmt"

	"github.com/min0625/gsyncmap"
)

func main() {
	var m gsyncmap.Map[string, string]

	m.Store("k1", "v1")
	fmt.Println(m.Load("k1"))
	fmt.Println(m.Load("k2"))

	m.Delete("k1")
	fmt.Println(m.Load("k1"))

}
Output:
v1 true
 false
 false

func (*Map[Key, Value]) Clear added in v0.3.0

func (m *Map[Key, Value]) Clear()

Clear deletes all the entries, resulting in an empty Map.

Example
package main

import (
	"fmt"

	"github.com/min0625/gsyncmap"
)

func main() {
	var m gsyncmap.Map[string, string]

	fmt.Println(m.Load("k1"))
	fmt.Println(m.Load("k2"))
	m.Store("k1", "v1")
	m.Store("k2", "v2")
	fmt.Println(m.Load("k1"))
	fmt.Println(m.Load("k2"))
	m.Clear()
	fmt.Println(m.Load("k1"))
	fmt.Println(m.Load("k2"))

}
Output:
 false
 false
v1 true
v2 true
 false
 false

func (*Map[Key, Value]) CompareAndDelete deprecated added in v0.2.0

func (m *Map[Key, Value]) CompareAndDelete(key Key, oldVal Value) (deleted bool)

CompareAndDelete deletes the entry for key if its value is equal to oldVal.

Deprecated: CompareAndDelete panics at runtime if Value is not a comparable type (e.g. slice, map, or func). Use ComparableMap.CompareAndDelete instead to enforce comparability at compile time.

func (*Map[Key, Value]) CompareAndSwap deprecated added in v0.2.0

func (m *Map[Key, Value]) CompareAndSwap(key Key, oldVal, newVal Value) bool

CompareAndSwap swaps the oldVal and newVal values for key if the value stored in the map is equal to oldVal.

Deprecated: CompareAndSwap panics at runtime if Value is not a comparable type (e.g. slice, map, or func). Use ComparableMap.CompareAndSwap instead to enforce comparability at compile time.

func (*Map[Key, Value]) Delete

func (m *Map[Key, Value]) Delete(key Key)

Delete deletes the value for a key.

func (*Map[Key, Value]) Load

func (m *Map[Key, Value]) Load(key Key) (value Value, ok bool)

Load returns the value stored in the map for a key, or the zero value if no value is present. The ok result indicates whether value was found in the map.

func (*Map[Key, Value]) LoadAndDelete

func (m *Map[Key, Value]) LoadAndDelete(key Key) (value Value, loaded bool)

LoadAndDelete deletes the value for a key, returning the previous value if any. The loaded result reports whether the key was present.

Example
package main

import (
	"fmt"

	"github.com/min0625/gsyncmap"
)

func main() {
	var m gsyncmap.Map[string, string]

	m.Store("k1", "v1")

	fmt.Println(m.LoadAndDelete("k1"))
	fmt.Println(m.Load("k1"))
	fmt.Println(m.LoadAndDelete("k1"))
	fmt.Println(m.Load("k1"))

}
Output:
v1 true
 false
 false
 false

func (*Map[Key, Value]) LoadOrStore

func (m *Map[Key, Value]) LoadOrStore(key Key, value Value) (actual Value, loaded bool)

LoadOrStore returns the existing value for the key if present. Otherwise, it stores and returns the given value. The loaded result is true if the value was loaded, false if stored.

Example
package main

import (
	"fmt"

	"github.com/min0625/gsyncmap"
)

func main() {
	var m gsyncmap.Map[string, string]

	fmt.Println(m.LoadOrStore("k1", "v1"))
	fmt.Println(m.Load("k1"))
	fmt.Println(m.LoadOrStore("k1", "v2"))
	fmt.Println(m.Load("k1"))

}
Output:
v1 false
v1 true
v1 true
v1 true

func (*Map[Key, Value]) Range

func (m *Map[Key, Value]) Range(f func(key Key, value Value) bool)

Range calls f sequentially for each key and value present in the map. If f returns false, range stops the iteration.

Range does not necessarily correspond to any consistent snapshot of the Map's contents: no key will be visited more than once, but if the value for any key is stored or deleted concurrently, Range may reflect any mapping for that key from any point during the Range call.

Example
package main

import (
	"fmt"

	"github.com/min0625/gsyncmap"
)

func main() {
	var m gsyncmap.Map[string, string]

	m.Store("k1", "v1")
	m.Store("k2", "v2")
	m.Store("k3", "v3")

	m.Range(func(key, value string) bool {
		fmt.Println(key, value)
		return true
	})

}
Output:
k1 v1
k2 v2
k3 v3
Example (Break)
package main

import (
	"fmt"

	"github.com/min0625/gsyncmap"
)

func main() {
	var m gsyncmap.Map[string, string]

	m.Store("k1", "v1")
	m.Store("k2", "v2")
	m.Store("k3", "v3")

	var cnt int

	m.Range(func(_, _ string) bool {
		cnt++
		return false
	})

	fmt.Println(cnt)

}
Output:
1

func (*Map[Key, Value]) Store

func (m *Map[Key, Value]) Store(key Key, value Value)

Store sets the value for a key.

func (*Map[Key, Value]) Swap added in v0.2.0

func (m *Map[Key, Value]) Swap(key Key, value Value) (previous Value, loaded bool)

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

Example
package main

import (
	"fmt"

	"github.com/min0625/gsyncmap"
)

func main() {
	var m gsyncmap.Map[string, string]

	fmt.Println(m.Load("k1"))
	fmt.Println(m.Swap("k1", "v1"))
	fmt.Println(m.Load("k1"))
	fmt.Println(m.Swap("k1", "v2"))
	fmt.Println(m.Load("k1"))

}
Output:
 false
 false
v1 true
v1 true
v2 true

Jump to

Keyboard shortcuts

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