Comment supprimer les clés sélectionnées d'une carte? Est-il sûr de combiner delete()
avec range, comme dans le code ci-dessous?
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)
}
}
la source
func (a T) expired() bool
interface. Pour les besoins de cet exemple, vous pouvez essayer: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 réponse de Sebastian est exacte, mais je voulais savoir pourquoi c'était sûr, alors j'ai fouillé dans le code source de Map . Cela ressemble à un appel à
delete(k, v)
, il définit simplement un indicateur (ainsi que la modification de la valeur de comptage) au lieu de supprimer réellement la valeur:(Vide est une constante pour la valeur
0
)Ce que la carte semble réellement faire est d'allouer un nombre défini de compartiments en fonction de la taille de la carte, qui augmente au fur et à mesure que vous effectuez des insertions au taux de
2^B
(à partir de ce code source ):Il y a donc presque toujours plus de buckets alloués que vous n'en utilisez, et lorsque vous effectuez un
range
over the map, il vérifie latophash
valeur de chaque bucket2^B
pour voir s'il peut l'ignorer.Pour résumer,
delete
dans unrange
est sûr parce que les données sont techniquement toujours là, mais quand il vérifie le,tophash
il voit qu'il peut simplement l'ignorer et ne pas l'inclure dans l'range
opération que vous effectuez. Le code source comprend même unTODO
:Cela explique pourquoi l'utilisation de la
delete(k,v)
fonction ne libère pas réellement de mémoire, mais la supprime simplement de la liste des buckets auxquels vous êtes autorisé à accéder. Si vous souhaitez libérer de la mémoire réelle, vous devrez rendre la carte entière inaccessible afin que le garbage collection intervienne. Vous pouvez le faire en utilisant une ligne commela source
Je me demandais si une fuite de mémoire pouvait se produire. J'ai donc écrit un programme de test:
On dirait que GC libère la mémoire. Alors ça va.
la source
Bref oui. Voir les réponses précédentes.
Et aussi ceci, d' ici :
La question à laquelle il répond concerne la modification des éléments cartographiques en place lors d'une
range
opération, c'est pourquoi il mentionne «l'itération actuelle». Mais c'est également pertinent ici: vous pouvez supprimer des clés pendant une plage, ce qui signifie simplement que vous ne les verrez pas plus tard dans la plage (et si vous les avez déjà vues, c'est pas grave).la source