Wie lösche ich eine Karte in Go?

85

Ich suche so etwas wie die c ++ - Funktion .clear() für den primitiven Typ map.

Oder sollte ich stattdessen einfach eine neue Karte erstellen?

Update: Vielen Dank für Ihre Antworten. Beim Betrachten der Antworten wurde mir gerade klar, dass das Erstellen einer neuen Karte manchmal zu Inkonsistenzen führen kann, die wir nicht wollen. Betrachten Sie das folgende Beispiel:

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"])
}

Ich meine, dies unterscheidet sich immer noch von der .clear()Funktion in c ++, die den Inhalt im Objekt löscht.

Lavin
quelle
1
Siehe auch diese Diskussion: groups.google.com/d/topic/golang-nuts/6yHDC7IYCj4/discussion
perreal
1
Es gibt auch Diskussionen über die eingebaute Säuberung
perreal

Antworten:

108

Sie sollten wahrscheinlich nur eine neue Karte erstellen. Es gibt keinen wirklichen Grund, sich die Mühe zu machen, eine vorhandene zu löschen, es sei denn, dieselbe Karte wird von mehreren Codeteilen referenziert, und ein Teil muss die Werte explizit löschen, sodass diese Änderung für die anderen Codeteile sichtbar ist.

Also ja, du solltest wahrscheinlich nur sagen

mymap = make(map[keytype]valtype)

Wenn Sie die vorhandene Karte aus irgendeinem Grund wirklich löschen müssen, ist dies einfach genug:

for k := range m {
    delete(m, k)
}
Lily Ballard
quelle
1
Das Löschen von Elementen nacheinander ist also der einzige Weg, dies zu tun?
Lavin
@lavin: Ja. Es gibt keine eingebaute Funktion, um dies zu tun, und Sie können keine Bibliotheksfunktion haben, die dies für beliebige Karten tut. Aber es sind sowieso nur 3 Zeilen.
Lily Ballard
6
Ist es wirklich in Ordnung, den Inhalt einer Karte zu ändern, während alle Werte durchlaufen werden? Andere Sprachen funktionieren damit nicht richtig.
John Jeffery
5
@ JohnJeffery: Ich habe dies getestet, bevor ich es gepostet habe. Scheint zu funktionieren. Die tatsächliche Sprache aus der Spezifikation besagt, 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.dass dies unterstützt wird.
Lily Ballard
18
Ab Go 1.11 werden Kartenlöschvorgänge dieses Formulars vom Compiler optimiert. github.com/golang/go/blob/master/doc/go1.11.html
Benjamin B.
20

Im Gegensatz zu C ++ ist Go eine Müllsammelsprache. Sie müssen die Dinge etwas anders denken.

Wenn Sie eine neue Karte erstellen

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

Die ursprüngliche Karte wird irgendwann im Müll gesammelt. Sie müssen es nicht manuell löschen. Denken Sie jedoch daran, dass Karten (und Slices) Referenztypen sind. Sie erstellen sie mit make(). Die zugrunde liegende Karte wird nur dann mit Müll gesammelt, wenn keine Verweise darauf vorhanden sind. Also, wenn Sie es tun

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

Das ursprüngliche Array wird nicht durch Müll gesammelt (bis b durch Müll gesammelt wird oder b auf etwas anderes verweist).

John Smith
quelle
2
// 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{}
Sumer
quelle
-5

Wenn Sie dies in einer Schleife versuchen, können Sie die Initialisierung nutzen, um die Karte für Sie zu löschen. Zum Beispiel:

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")
}

Wenn Sie dies ausführen, wird die vorherige Karte gelöscht und mit einer leeren Karte begonnen. Dies wird durch die Ausgabe überprüft:

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

For map instance 1
dog Spot
-----------
leemic
quelle
3
Das heißt nicht, die Karte zu löschen, sondern eine neue Karte zu erstellen und in jeder Schleife an eine lokale Variable mit demselben Namen zu binden.
Delaney