Supposons que j'ai ces types:
type Attribute struct {
Key, Val string
}
type Node struct {
Attr []Attribute
}
et que je veux itérer sur les attributs de mon nœud pour les changer.
J'aurais aimé pouvoir faire:
for _, attr := range n.Attr {
if attr.Key == "href" {
attr.Val = "something"
}
}
mais ce attr
n'est pas un pointeur, cela ne fonctionnerait pas et je dois le faire:
for i, attr := range n.Attr {
if attr.Key == "href" {
n.Attr[i].Val = "something"
}
}
Existe-t-il un moyen plus simple ou plus rapide? Est-il possible d'obtenir directement des pointeurs range
?
Evidemment, je ne veux pas changer les structures juste pour l'itération et des solutions plus verbeuses ne sont pas des solutions.
Array.prototype.forEach
JavaScript?forEach
commence nécessairement par une assertion de type. Ce n'est pas vraiment mieux queattr := &n.Attr[i]
.Réponses:
Non, l'abréviation souhaitée n'est pas possible.
La raison en est que
range
copie les valeurs de la tranche sur laquelle vous effectuez une itération. La spécification sur la gamme dit:Ainsi, range utilise
a[i]
comme deuxième valeur pour les tableaux / tranches, ce qui signifie en fait que la valeur est copiée, ce qui rend la valeur d'origine intouchable.Ce comportement est illustré par le code suivant :
Le code vous imprime des emplacements de mémoire complètement différents pour la valeur de la plage et la valeur réelle dans la tranche:
Donc, la seule chose que vous pouvez faire est d'utiliser des pointeurs ou l'index, comme déjà proposé par jnml et peterSO.
la source
a[i]
boucle for et le au momenta[i]
où nous écrivons? Cela ressemble à la même chose mais ce n'est pas le cas, non?range
renvoiea[i]
sa deuxième valeur de retour. Cette opération,val = a[i]
comme effectuée parrange
crée une copie de la valeur afin que toute opération d'écritureval
soit appliquée à une copie.Vous semblez demander quelque chose d'équivalent à ceci:
Production:
Cela évite de créer une copie - éventuellement volumineuse - des
Attribute
valeurs de type , au détriment des vérifications des limites de tranche. Dans votre exemple, le typeAttribute
est relativement petit, deuxstring
références de tranche: 2 * 3 * 8 = 48 octets sur une machine à architecture 64 bits.Vous pouvez aussi simplement écrire:
Mais, le moyen d'obtenir un résultat équivalent avec une
range
clause, qui crée une copie mais minimise les vérifications des limites de tranche, est:la source
value := &someMap[key]
cela ne fonctionnera pas sisomeMap
c'est unmap
*attr.Val = "something"
J'adapterais votre dernière suggestion et utiliserais la version indexée de range.
Il me semble plus simple de se référer
n.Attr[i]
explicitement à la fois à la ligne qui testeKey
et à la ligne qui définitVal
, plutôt que d'utiliserattr
pour l'un etn.Attr[i]
pour l'autre.la source
Par exemple:
Terrain de jeux
Production
Approche alternative:
Terrain de jeux
Production:
la source
go.net/html
paquet)