Метод sync.Map.LoadOrStore
Метод LoadOrStore структуры sync.Map атомарно выполняет операцию получения значения по ключу или его сохранения, если ключ отсутствует. Первым параметром метод принимает ключ, вторым — значение для сохранения. Метод возвращает два значения: фактическое значение, связанное с ключом (загруженное или только что сохраненное), и булев флаг true, если значение было загружено из карты, или false, если значение было сохранено. Этот метод гарантирует, что операция чтения или записи выполняется атомарно и безопасна для конкурентного использования.
Синтаксис
val, loaded := m.LoadOrStore(key, value)
Пример
Давайте попробуем загрузить значение по ключу, который отсутствует в карте:
package main
import (
"fmt"
"sync"
)
func main() {
var m sync.Map
val, loaded := m.LoadOrStore("key1", "hello")
fmt.Printf("val: %v, loaded: %v\n", val, loaded)
}
Результат выполнения кода:
"val: hello, loaded: false"
Так как ключа "key1" нет в карте, метод сохранил значение "hello" и вернул его, а флаг loaded равен false.
Пример
Теперь попробуем загрузить значение по ключу, который уже существует в карте:
package main
import (
"fmt"
"sync"
)
func main() {
var m sync.Map
m.Store("key2", 42)
val, loaded := m.LoadOrStore("key2", 100)
fmt.Printf("val: %v, loaded: %v\n", val, loaded)
}
Результат выполнения кода:
"val: 42, loaded: true"
Поскольку ключ "key2" уже есть в карте, метод вернул существующее значение 42 и флаг loaded равен true, а переданное значение 100 было проигнорировано.
Пример
Пример использования метода в конкурентной среде с несколькими горутинами:
package main
import (
"fmt"
"sync"
)
func main() {
var m sync.Map
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
val, loaded := m.LoadOrStore("shared", i)
fmt.Printf("goroutine %d: val=%v, loaded=%v\n", i, val, loaded)
}(i)
}
wg.Wait()
}
Результат выполнения кода (порядок может отличаться):
"goroutine 9: val=0, loaded=true"
"goroutine 7: val=0, loaded=true"
"goroutine 5: val=0, loaded=true"
"goroutine 3: val=0, loaded=true"
"goroutine 1: val=0, loaded=true"
"goroutine 8: val=0, loaded=true"
"goroutine 6: val=0, loaded=true"
"goroutine 4: val=0, loaded=true"
"goroutine 2: val=0, loaded=true"
"goroutine 0: val=0, loaded=false"
В этом примере только первая горутина, которая успела вызвать LoadOrStore, сохранит значение (флаг loaded будет false). Все остальные горутины получат уже сохраненное значение и флаг loaded равный true, что гарантирует, что значение будет сохранено только один раз.
Смотрите также
-
метод
sync.Map.Store,
который просто сохраняет значение по ключу -
метод
sync.Map.Load,
который загружает значение по ключу -
метод
sync.Map.LoadAndDelete,
который загружает и удаляет значение по ключу -
метод
sync.Map.Swap,
который атомарно заменяет значение по ключу