¿Cómo se pueden eliminar las claves seleccionadas de un mapa? ¿Es seguro combinarlo delete()
con el rango, como en el siguiente código?
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)
}
}
fuente
func (a T) expired() bool
interfaz. Para los propósitos de este ejemplo, puede intentar: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);
}
}
La respuesta de Sebastian es precisa, pero quería saber por qué era segura, así que investigé el código fuente del mapa . Parece que en una llamada a
delete(k, v)
, básicamente solo establece un indicador (además de cambiar el valor de conteo) en lugar de eliminar el valor:(Vacío es una constante para el valor
0
)Lo que el mapa parece estar haciendo realmente es asignar un número establecido de cubetas dependiendo del tamaño del mapa, que crece a medida que realiza inserciones a la velocidad de
2^B
(a partir de este código fuente ):Por lo tanto, casi siempre hay más depósitos asignados de los que está utilizando, y cuando hace un
range
sobre el mapa, verifica eltophash
valor de cada depósito2^B
para ver si puede omitirlo.Para resumir,
delete
dentro de arange
es seguro porque los datos técnicamente todavía están allí, pero cuando lo compruebatophash
, ve que puede omitirlo y no incluirlo en cualquierrange
operación que esté realizando. El código fuente incluso incluye unTODO
:Esto explica por qué el uso de la
delete(k,v)
función en realidad no libera memoria, solo la elimina de la lista de cubos a los que tiene acceso. Si desea liberar la memoria real, deberá hacer que todo el mapa sea inalcanzable para que intervenga la recolección de basura. Puede hacerlo usando una línea comofuente
Me preguntaba si podría ocurrir una pérdida de memoria. Entonces escribí un programa de prueba:
Parece que GC libera la memoria. Entonces está bien.
fuente
En resumen, si. Ver respuestas anteriores.
Y también esto, desde aquí :
La pregunta que está respondiendo es sobre la modificación de los elementos del mapa en su lugar durante una
range
operación, por lo que menciona la "iteración actual". Pero también es relevante aquí: puede eliminar claves durante un rango, y eso solo significa que no las verá más adelante en el rango (y si ya las vio, está bien).fuente