Como limpar um mapa em Go?

86

Estou procurando algo como a função c ++ .clear() para o tipo primitivo map.

Ou devo apenas criar um novo mapa?

Atualização: Obrigado por suas respostas. Olhando para as respostas, acabei de perceber que às vezes a criação de um novo mapa pode levar a alguma inconsistência que não queremos. Considere o seguinte exemplo:

var a map[string]string
var b map[string]string

func main() {
    a = make(map[string]string)
    b=a
    a["hello"]="world"
    a = nil
    fmt.Println(b["hello"])
}

Quer dizer, isso ainda é diferente da .clear()função em c ++, que limpará o conteúdo do objeto.

lavin
fonte
1
veja também esta discussão: groups.google.com/d/topic/golang-nuts/6yHDC7IYCj4/discussion
perreal
1
também há discussão sobre purga embutida
perreal

Respostas:

110

Você provavelmente deve apenas criar um novo mapa. Não há nenhum motivo real para se preocupar em tentar limpar um existente, a menos que o mesmo mapa esteja sendo referido por várias partes do código e uma parte precise explicitamente limpar os valores de forma que essa alteração seja visível para as outras partes do código.

Então, sim, você provavelmente deveria apenas dizer

mymap = make(map[keytype]valtype)

Se você realmente precisa limpar o mapa existente por qualquer motivo, isso é bastante simples:

for k := range m {
    delete(m, k)
}
Lily Ballard
fonte
1
Então, excluir os elementos um por um é a única maneira de fazer isso?
lavin
@lavin: Sim. Não há função incorporada para fazer isso, e você não pode ter uma função de biblioteca que faça isso para mapas arbitrários. Mas são apenas 3 linhas de qualquer maneira.
Lily Ballard
6
É realmente correto modificar o conteúdo de um mapa enquanto itera por todos os valores? Outros idiomas não funcionarão corretamente com isso.
John Jeffery
5
@JohnJeffery: Testei isso antes de postar. Parece funcionar. O idioma real da especificação diz The iteration order over maps is not specified and is not guaranteed to be the same from one iteration to the next. If map entries that have not yet been reached are deleted during iteration, the corresponding iteration values will not be produced. If map entries are inserted during iteration, the behavior is implementation-dependent, but the iteration values for each entry will be produced at most once. If the map is nil, the number of iterations is 0.Isso sugere que é compatível.
Lily Ballard
18
A partir do Go 1.11, as operações de limpeza de mapa deste formulário são otimizadas pelo compilador. github.com/golang/go/blob/master/doc/go1.11.html
Benjamin B.
21

Ao contrário do C ++, Go é uma linguagem com coleta de lixo. Você precisa pensar as coisas de maneira um pouco diferente.

Quando você faz um novo mapa

a := map[string]string{"hello": "world"}
a = make(map[string]string)

o mapa original será eventualmente coletado como lixo; você não precisa limpá-lo manualmente. Mas lembre-se de que os mapas (e fatias) são tipos de referência; você os cria com make(). O mapa subjacente será coletado como lixo apenas quando não houver referências a ele. Assim, quando você faz

a := map[string]string{"hello": "world"}
b := a
a = make(map[string]string)

o array original não será coletado como lixo (até que b seja coletado como lixo ou b se refira a outra coisa).

John smith
fonte
3
// Method - I , say book is name of map
for k := range book {
    delete(book, k)
}

// Method - II
book = make(map[string]int)

// Method - III
book = map[string]int{}
verão
fonte
-5

Se você está tentando fazer isso em um loop, pode aproveitar a inicialização para limpar o mapa para você. Por exemplo:

for i:=0; i<2; i++ {
    animalNames := make(map[string]string)
    switch i {
        case 0:
            animalNames["cat"] = "Patches"
        case 1:
            animalNames["dog"] = "Spot";
    }

    fmt.Println("For map instance", i)
    for key, value := range animalNames {
        fmt.Println(key, value)
    }
    fmt.Println("-----------\n")
}

Quando você executa isso, ele limpa o mapa anterior e começa com um mapa vazio. Isso é verificado pela saída:

$ go run maptests.go 
For map instance 0
cat Patches
-----------

For map instance 1
dog Spot
-----------
leêmico
fonte
3
Isso não está limpando o mapa, mas fazendo um novo mapa e vinculando a uma variável local com o mesmo nome a cada loop.
Delaney