Como remover as chaves selecionadas de um mapa? É seguro combinar delete()
com o alcance, como no código abaixo?
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
Everton
fonte
fonte
func (a T) expired() bool
interface. Para os fins deste exemplo, você pode tentar: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);
}
}
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:(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 ):Portanto, quase sempre há mais buckets alocados do que você está usando, e quando você faz um
range
over-the-map, ele verifica otophash
valor de cada bucket2^B
para ver se ele pode ignorá-lo.Para resumir, o
delete
dentro de umrange
é 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 qualquerrange
operação que você esteja executando. O código fonte ainda inclui umTODO
: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 comofonte
Fiquei me perguntando se um vazamento de memória poderia acontecer. Então eu escrevi um programa de teste:
Parece que o GC libera a memória. Então está tudo bem.
fonte
Em suma, sim. Veja as respostas anteriores.
E também isso, daqui :
A pergunta que ele está respondendo é sobre a modificação dos elementos do mapa durante uma
range
operação, e é por isso que ele menciona a "iteração atual". Mas também é relevante aqui: você pode excluir as chaves durante um intervalo, e isso significa apenas que você não as verá mais tarde (e se você já as viu, tudo bem).fonte