Skip to content

Latest commit

 

History

History

06_map

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 

🗺️ sync.Map in Go

💡 What is sync.Map?

sync.Map is a concurrent map implementation in Go, designed to be safe for concurrent use by multiple goroutines. It provides a way to safely store and retrieve key-value pairs in a map-like structure, without requiring explicit locking and unlocking using sync.Mutex.

It’s particularly useful in scenarios where you have many goroutines reading and writing to the map simultaneously. The map is optimized for cases where reads are more frequent than writes, making it suitable for caches, lookups, or storing shared data in highly concurrent applications.

  • Purpose: Provides thread-safe operations for maps.
  • How it works: Uses fine-grained locks internally, which improves performance compared to using sync.Mutex in highly concurrent environments.

📝 How to Use sync.Map

  1. Create a sync.Map

    • You can create a sync.Map by initializing it with an empty struct.
  2. Store and Retrieve Values

    • Use Store(key, value) to store a key-value pair.
    • Use Load(key) to retrieve a value by key.
    • Use Delete(key) to remove a key-value pair.
    • Use LoadOrStore(key, value) to retrieve the value for a key, or store the value if it doesn’t exist.
  3. Iterate Over sync.Map

    • You can iterate over the map using Range, which allows you to apply a function to each key-value pair.

💡 Example: Using sync.Map

package main

import (
	"fmt"
	"sync"
)

func main() {
	var m sync.Map
	
	m.Store("user_id", 98765)              
	m.Store("user_name", "dark_vard")       
	m.Store("account_balance", 9999.99)    
	m.Store("subscription_active", true)   
	m.Store("last_login", "2024-12-01")    

	fmt.Println("Iterating over map and printing key-value pairs:")
	m.Range(func(key, value any) bool {
		if key == "account_balance" {
			fmt.Println("-> Found account_balance, stopping iteration.")
			return false
		}
		fmt.Printf("Key: %v, Value: %v\n", key, value)
		return true
	})

	fmt.Println("Deleting 'last_login' key...")
	m.Delete("last_login")

	if value, ok := m.Load("last_login"); ok {
		fmt.Println("Found last_login:", value)
	} else {
		fmt.Println("Last login was deleted.")
	}

	fmt.Println("Using LoadOrStore for 'last_login'...")
	if value, loaded := m.LoadOrStore("last_login", "2024-12-01"); loaded {
		fmt.Println("Loaded existing value for last_login:", value)
	} else {
		fmt.Println("Stored new value for last_login:", value)
	}
}

Key Concepts in sync.Map

  • Concurrency-Safe Operations: sync.Map allows for concurrent access, eliminating the need for explicit locking.
  • Optimized for Read-Heavy Operations: It performs well in environments where read operations are much more frequent than writes.
  • Lazy Initialization: It supports lazy loading of values using LoadOrStore.

💡 Real-World Use Cases for sync.Map

  1. Cache Implementation

    • Scenario: A caching system needs to store and retrieve data frequently with high concurrency.
    • Solution: Use sync.Map to store cache entries and ensure thread-safe access without locking overhead.
  2. Global State Management

    • Scenario: When managing global state shared between many goroutines (e.g., configuration settings, feature flags).
    • Solution: Use sync.Map for efficient and thread-safe access to shared global data.
  3. Counting or Tracking Metrics

    • Scenario: Tracking counts, logs, or metrics that are frequently updated by different goroutines.
    • Solution: Use sync.Map to store counts, and update them concurrently in a thread-safe manner.

⚠️ Best Practices for sync.Map

  • Avoid Excessive Deletions: Frequently deleting keys in sync.Map could affect performance, as it internally uses a technique to handle deleted items efficiently.
  • Key Type: The key type should be comparable, meaning it can be used in equality comparisons (e.g., strings, integers).
  • Use for Read-Heavy Scenarios: sync.Map shines in read-heavy workloads, so it’s not ideal for scenarios with frequent writes and deletions.

✅ How to Use sync.Map Correctly

To use sync.Map effectively:

  1. Use for Read-Heavy Workloads: sync.Map is ideal for scenarios where reads are more frequent than writes.
  2. Avoid Frequent Deletions: Frequent deletes could harm performance, so be mindful of using Delete often.
  3. Ensure Proper Key Comparability: Only use types as keys that are comparable (e.g., strings, integers).