๐ŸŽ“ A1Learner
๐Ÿ”
0 of 28 lessons completed

Go Sync Map

A sync map is a shared map that stays safe when many goroutines use it at the same time. It holds pairs of keys and values like a plain map.

Store and Load

Store saves a name under the key name. Load reads it back with a true flag. A key that was never stored reads back as <nil> with a false flag.

package main

import (
	"fmt"
	"sync"
)

func main() {
	var m sync.Map
	m.Store("name", "Ada")
	value, ok := m.Load("name")
	fmt.Println(value, ok)
	value, ok = m.Load("city")
	fmt.Println(value, ok)
}

LoadOrStore keeps the first value

The first call stores red and reports false. The second call finds red already there, reports true, and keeps red.

package main

import (
	"fmt"
	"sync"
)

func main() {
	var m sync.Map
	actual, loaded := m.LoadOrStore("color", "red")
	fmt.Println(actual, loaded)
	actual, loaded = m.LoadOrStore("color", "blue")
	fmt.Println(actual, loaded)
}

Sorted keys fix the print order

Range collects the keys into a slice. The keys are sorted before the loop prints each pair.

package main

import (
	"fmt"
	"sort"
	"sync"
)

func main() {
	var m sync.Map
	m.Store("banana", 2)
	m.Store("apple", 1)
	m.Store("cherry", 3)
	keys := []string{}
	m.Range(func(key, value any) bool {
		keys = append(keys, key.(string))
		return true
	})
	sort.Strings(keys)
	for _, key := range keys {
		value, _ := m.Load(key)
		fmt.Println(key, value)
	}
}

Example

package main

import (
	"fmt"
	"sort"
	"sync"
)

func store(m *sync.Map, wg *sync.WaitGroup, key string, value int) {
	defer wg.Done()
	m.Store(key, value)
}

func main() {
	var m sync.Map
	var wg sync.WaitGroup
	wg.Add(3)
	go store(&m, &wg, "north", 3)
	go store(&m, &wg, "south", 1)
	go store(&m, &wg, "east", 2)
	wg.Wait()
	keys := []string{}
	m.Range(func(key, value any) bool {
		keys = append(keys, key.(string))
		return true
	})
	sort.Strings(keys)
	for _, key := range keys {
		value, _ := m.Load(key)
		fmt.Println(key, value)
	}
}

Key points

  • A sync map holds key and value pairs that many goroutines can share at once.
  • Store saves a value under a key.
  • Load returns the value for a key and a flag that tells whether the key was found.
  • LoadOrStore returns the stored value when the key is already there.
  • LoadOrStore saves the given value when the key is still missing.
  • Range visits every pair in the map, but the order changes from run to run.
  • Collect the keys and sort them when the pairs must print in a fixed order.

In this example, three goroutines each store one pair in the same sync map. Main waits with a WaitGroup until all three stores finish. Range then collects the keys and the keys are sorted. The pairs print in sorted key order, so the output never changes.

Try it Yourself

Edit the code, then press Run.

Running is simulated ยท Go Playground

Exercise

What does Load return for a key that was never stored?