Nehmen wir an, ich habe folgende Typen:
type Attribute struct {
Key, Val string
}
type Node struct {
Attr []Attribute
}
und dass ich die Attribute meines Knotens durchlaufen möchte, um sie zu ändern.
Am liebsten hätte ich Folgendes tun können:
for _, attr := range n.Attr {
if attr.Key == "href" {
attr.Val = "something"
}
}
aber da attr
es kein Zeiger ist, würde dies nicht funktionieren und ich muss tun:
for i, attr := range n.Attr {
if attr.Key == "href" {
n.Attr[i].Val = "something"
}
}
Gibt es einen einfacheren oder schnelleren Weg? Ist es möglich, Zeiger direkt abzurufen range
?
Natürlich möchte ich die Strukturen nicht nur für die Iteration ändern, und ausführlichere Lösungen sind keine Lösungen.
Array.prototype.forEach
JavaScript?forEach
notwendigerweise mit einer Typzusicherung beginnen würde. Das ist nicht wirklich besser alsattr := &n.Attr[i]
.Antworten:
Nein, die gewünschte Abkürzung ist nicht möglich.
Der Grund dafür ist, dass
range
die Werte aus dem Slice kopiert werden, über das Sie iterieren. Die Spezifikation über die Reichweite lautet:Daher wird range
a[i]
als zweiter Wert für Arrays / Slices verwendet. Dies bedeutet effektiv, dass der Wert kopiert wird, wodurch der ursprüngliche Wert unberührbar wird.Dieses Verhalten wird durch den folgenden Code demonstriert :
Der Code druckt Ihnen völlig unterschiedliche Speicherorte für den Wert aus dem Bereich und den tatsächlichen Wert im Slice:
Sie können also entweder Zeiger oder den Index verwenden, wie bereits von jnml und peterSO vorgeschlagen.
quelle
a[i]
der for-Schleife und dera[i]
beim Schreiben? Es sieht genauso aus, ist es aber nicht, oder?range
gibta[i]
als zweiten Rückgabewert zurück. Dieser Vorgang,val = a[i]
wie getan , indemrange
erstellt eine Kopie des Wertes so dass jeder Schreibvorgangval
auf eine Kopie angelegt wird.Sie scheinen nach etwas Äquivalentem zu fragen:
Ausgabe:
Dadurch wird vermieden
Attribute
, dass auf Kosten von Slice-Bound-Checks eine - möglicherweise große - Kopie von Typwerten erstellt wird. In Ihrem Beispiel ist der TypAttribute
relativ klein, zweistring
Slice-Referenzen: 2 * 3 * 8 = 48 Byte auf einem 64-Bit-Architekturcomputer.Sie könnten auch einfach schreiben:
Der Weg, um ein gleichwertiges Ergebnis mit einer
range
Klausel zu erhalten, die eine Kopie erstellt, aber die Überprüfung der Slice-Grenzen minimiert, ist:quelle
value := &someMap[key]
nicht funktionieren wird, wennsomeMap
amap
*attr.Val = "something"
Ich würde Ihren letzten Vorschlag anpassen und die Nur-Index-Version des Bereichs verwenden.
Es scheint mir einfacher zu verweisen
n.Attr[i]
ausdrücklich sowohl in der Linie , dass die TestsKey
und die Linie , dass SätzeVal
, anstattattr
für ein undn.Attr[i]
für den anderen.quelle
Beispielsweise:
Spielplatz
Ausgabe
Alternativer Ansatz:
Spielplatz
Ausgabe:
quelle
go.net/html
Paket)