значение адреса, возвращаемое map.LoadOrStore, совпадает с входным значением в случае вложенных карт? - PullRequest
0 голосов
/ 27 июня 2018

Я делаю вложенную sync.Map , но мне интересно, могу ли я сохранить несколько строк кода, если значение, возвращаемое LoadOrStore, совпадает с вводом в случае карты, Я имею в виду это:

var mapa sync.Map
mapaInterFace, ok := sessiones.LoadOrStore(userID,mapa)
if ok {
    mapa,ok=mapaInterFace.(sync.Map)
    if !ok{
        return errors.New("type assertion")
    }
}

Если mapa было таким же, как и возвращаемое LoadOrStore при сохранении значения, я могу немедленно использовать его, но если нет, мне нужно добавить после предыдущего кода, утверждение типа:

mapa,ok=mapaInterFace.(sync.Map)
    if !ok{
        return errors.New("type assertion")
    }

и делая это часто, можно получить некрасивый код

Обновление: sessiones - это тип sync.Map

1 Ответ

0 голосов
/ 27 июня 2018

Как я объясню позже, вы должны использовать указатели для типов sync.Map. Поэтому мы можем упростить до:

var mapa, mapb = new(sync.Map), new(sync.Map)
var key string

if actual, loaded := mapa.LoadOrStore(key, mapb); loaded {
    if maps, ok := actual.(*sync.Map); ok {
        mapb = maps
    } else {
        // handle loaded value type assertion error
    }
}

Теперь назначения дешевы, потому что мы назначаем указатели (*sync.Map), а не структуры (sync.Map).


Синхронизация пакета

import "sync" 

карта типа

Карта похожа на интерфейс Go map [interface {}] {}, но безопасна для одновременное использование несколькими программами без дополнительной блокировки или координация. Загрузка, хранение и удаление выполняется в амортизированной константе время.

Тип карты является специализированным. Большая часть кода должна использовать простую карту Go вместо этого, с отдельной блокировкой или координацией, для лучшей безопасности типа и чтобы было проще поддерживать другие инварианты вместе с картой содержание.

Тип карты оптимизирован для двух распространенных случаев использования: (1) когда запись для данного ключа пишется только один раз, но читается много раз, как в кэши, которые только растут, или (2) когда несколько операций чтения, записи, и перезаписать записи для непересекающихся наборов ключей. В этих двух случаях использование карты может значительно уменьшить конфликт блокировок по сравнению с Go карта в паре с отдельным Mutex или RWMutex.

Нулевая карта пуста и готова к использованию. Карта не должна быть скопирована после первого использования.

type Map struct {
        // contains filtered or unexported fields
}

func (* Карта) LoadOrStore

func (m *Map) LoadOrStore(key, value interface{}) (actual interface{}, loaded bool)

LoadOrStore возвращает существующее значение для ключа, если оно присутствует. В противном случае он сохраняет и возвращает заданное значение. Загруженный результат Значение true, если значение было загружено, значение false, если сохранено.


A sync.Map нельзя копировать после первого использования.

В Go все аргументы и получатели передаются по значению, как по присваиванию (копии). Например, go vet сообщает об ошибке sync.Map,

// go vet: variable declaration copies lock value to arg: sync.Map contains sync.Mutex
var m sync.Map
var arg interface{} = m

и

var map1, map2 sync.Map
// go vet: call of map1.LoadOrStore copies lock value: sync.Map contains sync.Mutex
map1.LoadOrStore("key", map2)

Используйте указатели. Например,

    var m sync.Map
    var arg interface{} = &m

и

    var map1, map2 sync.Map
    map1.LoadOrStore("key", &map2)
...