A resposta de Sebastian é precisa, mas eu queria saber por que era seguro, então eu procurei no código-fonte do Mapa . Parece que em uma chamada para delete(k, v)
, basicamente, apenas define um sinalizador (além de alterar o valor da contagem) em vez de realmente excluir o valor:
b->tophash[i] = Empty;
(Vazio é uma constante para o valor 0
)
O que o mapa parece realmente estar fazendo é alocar um número definido de buckets, dependendo do tamanho do mapa, que cresce à medida que você executa inserções na taxa de 2^B
(a partir deste código-fonte ):
byte *buckets; // array of 2^B Buckets. may be nil if count==0.
Portanto, quase sempre há mais buckets alocados do que você está usando, e quando você faz um range
over-the-map, ele verifica o tophash
valor de cada bucket 2^B
para ver se ele pode ignorá-lo.
Para resumir, o delete
dentro de um range
é seguro porque os dados ainda estão tecnicamente disponíveis, mas quando verifica, tophash
ele vê que pode simplesmente ignorá-lo e não incluí-lo em qualquer range
operação que você esteja executando. O código fonte ainda inclui um TODO
:
// TODO: consolidate buckets if they are mostly empty
// can only consolidate if there are no live iterators at this size.
Isso explica por que o uso da delete(k,v)
função não libera memória, apenas a remove da lista de buckets que você tem permissão para acessar. Se você quiser liberar a memória real, precisará tornar o mapa inteiro inacessível para que a coleta de lixo entre. Você pode fazer isso usando uma linha como
map = nil