Как удалить выбранные ключи с карты? Безопасно ли комбинировать delete()
с диапазоном, как в приведенном ниже коде?
package main
import "fmt"
type Info struct {
value string
}
func main() {
table := make(map[string]*Info)
for i := 0; i < 10; i++ {
str := fmt.Sprintf("%v", i)
table[str] = &Info{str}
}
for key, value := range table {
fmt.Printf("deleting %v=>%v\n", key, value.value)
delete(table, key)
}
}
dictionary
for-loop
go
Эвертон
источник
источник
func (a T) expired() bool
интерфейс. В этом примере вы можете попробовать:m := make(map[int]int)
/* populate m here somehow */
for key := range (m) {
if key % 2 == 0 { /* this is just some condition, such as calling expired */
delete(m, key);
}
}
Ответ Себастьяна точен, но я хотел знать, почему это безопасно, поэтому я немного покопался в исходном коде карты . Похоже, что при вызове
delete(k, v)
он просто устанавливает флаг (а также меняет значение счетчика) вместо фактического удаления значения:(Пусто - это константа для значения
0
)На самом деле карта, по-видимому, выделяет определенное количество сегментов в зависимости от размера карты, который увеличивается по мере выполнения вставок со скоростью
2^B
(из этого исходного кода ):Таким образом, почти всегда выделяется больше сегментов, чем вы используете, и когда вы выполняете
range
переход по карте, он проверяет этоtophash
значение каждого сегмента в нем,2^B
чтобы увидеть, может ли он пропустить его.Подводя итог, можно сказать, что
delete
внутри arange
безопасно, потому что данные технически все еще там, но когда он проверяет,tophash
он видит, что может просто пропустить их и не включать в любуюrange
операцию, которую вы выполняете. Исходный код даже включаетTODO
:Это объясняет, почему использование
delete(k,v)
функции на самом деле не освобождает память, а просто удаляет ее из списка сегментов, к которым вам разрешен доступ. Если вы хотите освободить реальную память, вам нужно сделать всю карту недоступной, чтобы вмешалась сборка мусора. Вы можете сделать это, используя строку видаисточник
Мне было интересно, может ли произойти утечка памяти. Итак, я написал тестовую программу:
Похоже, сборщик мусора освобождает память. Так что все в порядке.
источник
Короче да. См. Предыдущие ответы.
А также отсюда :
Вопрос, на который он отвечает, касается изменения элементов карты на месте во время
range
операции, поэтому он упоминает «текущую итерацию». Но это также актуально здесь: вы можете удалять ключи во время диапазона, а это просто означает, что вы не увидите их позже в диапазоне (и если вы уже видели их, это нормально).источник