Ответ
map
в Go — это встроенная структура данных (хэш-таблица), которая используется для хранения пар ключ-значение.
Основные случаи использования:
- Кэширование: Хранение часто запрашиваемых данных в памяти для быстрого доступа.
- Счетчики: Подсчет частоты вхождений элементов (например, слов в тексте).
- Индексы: Быстрый поиск объекта по его уникальному идентификатору.
- Представление JSON:
map[string]interface{}
является стандартным способом для десериализации произвольных JSON-объектов.
Ключевые особенности map
:
- Это ссылочный тип. Нулевое значение
map
— этоnil
. Попытка записи вnil
-мапу вызовет панику.var m map[string]int // m[key] = 1 // паника: assignment to entry in nil map m = make(map[string]int) // Правильная инициализация
- Доступ, вставка и удаление в среднем имеют сложность O(1).
- Порядок итерации по элементам не гарантирован и может меняться от запуска к запуску.
Потокобезопасность
Стандартная map
в Go не является потокобезопасной. Одновременная запись и чтение из разных горутин приведет к состоянию гонки (race condition
) и возможной панике.
Есть два основных способа обеспечить потокобезопасность:
-
map
с мьютексом (sync.RWMutex
) Это самый распространенный и гибкий подход.RWMutex
позволяет множественные одновременные чтения, но эксклюзивный доступ для записи.type SafeMap struct { mu sync.RWMutex data map[string]int } func (sm *SafeMap) Get(key string) (int, bool) { sm.mu.RLock() // Блокировка на чтение defer sm.mu.RUnlock() val, ok := sm.data[key] return val, ok } func (sm *SafeMap) Set(key string, value int) { sm.mu.Lock() // Блокировка на запись defer sm.mu.Unlock() sm.data[key] = value }
Когда использовать: Когда у вас больше чтений, чем записей, или когда нужны сложные атомарные операции (например, прочитать, изменить и записать значение под одной блокировкой).
-
sync.Map
Специализированный тип, оптимизированный для двух сценариев:- Ключ записывается один раз, а затем читается много раз.
- Разные горутины работают с непересекающимися наборами ключей.
Когда использовать: В сценариях с высокой конкуренцией, где
RWMutex
может стать узким местом.sync.Map
избегает глобальной блокировки для многих операций.Недостатки: Более сложный API (
Load
,Store
,Delete
) и может быть медленнее, чемmap
с мьютексом, при малом количестве горутин или при частых записях.