Wie kann man ausgewählte Schlüssel von einer Karte entfernen? Ist es sicher, delete()
mit Reichweite zu kombinieren , wie im folgenden Code?
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)
}
}
quelle
func (a T) expired() bool
Schnittstelle implementiert . Für die Zwecke dieses Beispiels könnten Sie versuchen: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);
}
}
Sebastians Antwort ist korrekt, aber ich wollte wissen, warum es sicher ist, also habe ich mich ein wenig mit dem Map-Quellcode befasst . Es sieht aus wie bei einem Aufruf von
delete(k, v)
, es setzt im Grunde nur ein Flag (sowie das Ändern des Zählwerts), anstatt den Wert tatsächlich zu löschen:(Leer ist eine Konstante für den Wert
0
)Was die Karte tatsächlich zu tun scheint, ist die Zuweisung einer festgelegten Anzahl von Buckets in Abhängigkeit von der Größe der Karte, die wächst, wenn Sie Einfügungen mit der Rate von
2^B
(aus diesem Quellcode ) ausführen :Es werden also fast immer mehr Buckets zugewiesen, als Sie verwenden. Wenn Sie eine
range
Über-die-Karte ausführen, wird dertophash
Wert jedes Buckets darin überprüft, um festzustellen,2^B
ob er übersprungen werden kann.Zusammenfassend ist das
delete
innerhalb von arange
sicher, da die Daten technisch immer noch vorhanden sind. Wenn es jedoch überprüfttophash
, sieht es, dass es sie einfach überspringen und nicht in die vonrange
Ihnen ausgeführte Operation einbeziehen kann. Der Quellcode enthält sogarTODO
:Dies erklärt, warum die Verwendung der
delete(k,v)
Funktion den Speicher nicht freigibt, sondern nur aus der Liste der Buckets entfernt, auf die Sie zugreifen dürfen. Wenn Sie den eigentlichen Speicher freigeben möchten, müssen Sie die gesamte Karte nicht erreichbar machen, damit die Speicherbereinigung aktiviert wird. Sie können dies mit einer Zeile wie tunquelle
Ich habe mich gefragt, ob ein Speicherverlust auftreten könnte. Also habe ich ein Testprogramm geschrieben:
Es sieht so aus, als würde GC den Speicher freigeben. Also ist es okay.
quelle
Kurz gesagt, ja. Siehe vorherige Antworten.
Und auch das von hier aus :
Die Frage, die er beantwortet, betrifft das Ändern von Kartenelementen
range
, die während einer Operation vorhanden sind, weshalb er die "aktuelle Iteration" erwähnt. Aber es ist auch hier relevant: Sie können Schlüssel während eines Bereichs löschen, und das bedeutet nur, dass Sie sie später im Bereich nicht mehr sehen werden (und wenn Sie sie bereits gesehen haben, ist das in Ordnung).quelle