sync.Map.LoadAndDelete

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

Синтаксис

govalue, loaded := m.LoadAndDelete(key)

Метод принимает один параметр key — ключ для загрузки и удаления. Возвращает два значения: само значение и булев флаг loaded, который равен true, если ключ присутствовал в карте, и false — в противном случае.

Пример

Давайте создадим sync.Map, добавим в него несколько элементов и с помощью LoadAndDelete загрузим и удалим ключ:

gopackage main

import (
  "fmt"
  "sync"
)

func main() {
  var m sync.Map

  // Добавляем элементы в карту
  m.Store("one", 1)
  m.Store("two", 2)
  m.Store("three", 3)

  // Загружаем и удаляем ключ "two"
  val, loaded := m.LoadAndDelete("two")
  fmt.Printf("loaded: %v, value: %v\n", loaded, val)

  // Проверяем наличие ключа "two" после удаления
  _, exists := m.Load("two")
  fmt.Printf("key 'two' exists after delete: %v\n", exists)
}

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

go"loaded: true, value: 2"
"key 'two' exists after delete: false"

Как видно из примера, метод успешно загрузил значение для ключа "two" и удалил его из карты.

Пример

Рассмотрим случай, когда запрашиваемый ключ отсутствует в карте:

gopackage main

import (
  "fmt"
  "sync"
)

func main() {
  var m sync.Map

  // Попытка загрузить и удалить отсутствующий ключ
  val, loaded := m.LoadAndDelete("nonexistent")
  fmt.Printf("loaded: %v, value: %v\n", loaded, val)
}

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

go"loaded: false, value: <nil>"

В этом случае метод возвращает false и нулевое значение для типа, хранящегося в карте.

Пример

Продемонстрируем использование LoadAndDelete в конкурентной среде с несколькими горутинами:

gopackage main

import (
  "fmt"
  "sync"
)

func main() {
  var m sync.Map
  var wg sync.WaitGroup

  // Заполняем карту
  for i := 0; i < 5; i++ {
    m.Store(i, i*10)
  }

  // Запускаем несколько горутин для конкурентного удаления
  for i := 0; i < 5; i++ {
    wg.Add(1)
    go func(key int) {
      defer wg.Done()
      val, loaded := m.LoadAndDelete(key)
      if loaded {
        fmt.Printf("Goroutine deleted key %d with value %d\n", key, val)
      } else {
        fmt.Printf("Goroutine key %d not found\n", key)
      }
    }(i)
  }

  wg.Wait()
}

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

go"Goroutine deleted key 0 with value 0"
"Goroutine deleted key 1 with value 10"
"Goroutine deleted key 2 with value 20"
"Goroutine deleted key 3 with value 30"
"Goroutine deleted key 4 with value 40"

Этот пример показывает, что метод безопасен для использования из нескольких горутин одновременно.

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

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