Метод sync.Map.Range

Метод sync.Map.Range последовательно обходит все элементы карты, передавая каждый ключ и значение в функцию обратного вызова. Этот метод безопасен для использования из нескольких горутин и предоставляет консистентный снимок состояния карты на момент начала итерации.

Функция обратного вызова принимает два параметра: ключ и значение. Если она возвращает false, итерация немедленно прекращается. Важно отметить, что внутри функции обратного вызова нельзя вызывать методы sync.Map, изменяющие карту, кроме Delete, так как это может привести к взаимоблокировке.

Синтаксис

gom.Range(func(key, value interface{}) bool {
  // обработка элемента
  return true // продолжать итерацию
})

Метод принимает единственный параметр - функцию, которая будет вызвана для каждой пары ключ-значение. Функция должна возвращать bool: true для продолжения итерации или false для ее остановки.

Пример

Давайте создадим карту с несколькими элементами и выведем все ключи и значения на экран:

gopackage main

import (
  "fmt"
  "sync"
)

func main() {
  var m sync.Map

  m.Store("key1", 1)
  m.Store("key2", 2)
  m.Store("key3", 3)

  m.Range(func(key, value interface{}) bool {
    fmt.Printf("key: %v, value: %v\n", key, value)
    return true
  })
}

Результат выполнения кода (порядок может отличаться):

go"key: key1, value: 1"
"key: key2, value: 2"
"key: key3, value: 3"

Пример

Теперь давайте прервем итерацию после нахождения элемента с определенным значением:

gopackage main

import (
  "fmt"
  "sync"
)

func main() {
  var m sync.Map

  m.Store("a", 1)
  m.Store("b", 2)
  m.Store("c", 3)
  m.Store("d", 4)

  m.Range(func(key, value interface{}) bool {
    fmt.Printf("key: %v, value: %v\n", key, value)
    if value == 3 {
      fmt.Println("found value 3, stopping iteration")
      return false
    }
    return true
  })
}

Результат выполнения кода:

go"key: a, value: 1"
"key: b, value: 2"
"key: c, value: 3"
"found value 3, stopping iteration"

Пример

Покажем, как использовать Range для сбора всех ключей в слайс:

gopackage main

import (
  "fmt"
  "sync"
)

func main() {
  var m sync.Map
  var keys []string

  m.Store("first", 1)
  m.Store("second", 2)
  m.Store("third", 3)

  m.Range(func(key, value interface{}) bool {
    keys = append(keys, key.(string))
    return true
  })

  fmt.Println(keys)
}

Результат выполнения кода:

go[first second third]

Смотрите также

  • метод sync.Map.Store,
    который добавляет или обновляет элемент в карте
  • метод sync.Map.Load,
    который извлекает значение по ключу
  • метод sync.Map.Delete,
    который удаляет элемент из карты
  • метод sync.Map.LoadOrStore,
    который загружает значение или сохраняет новое