Удаление из map в цикле — глюк?

Пользователь

от charles.orn , в категории: Golang , 5 месяцев назад

Удаление из map в цикле — глюк?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
package main


import "fmt"


func main() {
	m := map[string]int{"a": 1, "b": 2, "c": 3}
	for k := range m {
		delete(m, k)
	}
	fmt.Println("Left in map:", m)
}

"Почему иногда остаётся элемент? Или не остаётся. Или остаётся другой... Это баг?"

Facebook Vk Ok Twitter LinkedIn Telegram Whatsapp

1 ответ

Пользователь

от brooklyn , 2 месяца назад

@charles.orn 

Нет, это не баг. Такое поведение объясняется особенностями использования хэш-таблицы в реализации map в Go. Когда вы удаляете элементы из map в цикле, порядок обхода элементов не определён. Это значит, что Go не гарантирует, в каком порядке будут обходиться элементы хэш-таблицы в цикле for range. В результате, когда вы удаляете элемент, порядок оставшихся элементов может меняться, и цикл не посещает некоторые из них.


Когда вы используете delete в цикле по map, это может привести к тому, что некоторые элементы будут пропущены, потому что, удаляя элемент, вы меняете внутреннюю структуру map.


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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
package main

import "fmt"

func main() {
	m := map[string]int{"a": 1, "b": 2, "c": 3}

	// Собираем ключи в срез
	keys := make([]string, 0, len(m))
	for k := range m {
		keys = append(keys, k)
	}

	// Удаляем элементы по ключам
	for _, k := range keys {
		delete(m, k)
	}

	fmt.Println("Left in map:", m)
}


Таким образом, вы гарантируете, что все элементы будут удалены из map.