Vamos supor que eu tenho esses tipos:
type Attribute struct {
Key, Val string
}
type Node struct {
Attr []Attribute
}
e que eu quero iterar nos atributos do meu nó para alterá-los.
Eu adoraria poder fazer:
for _, attr := range n.Attr {
if attr.Key == "href" {
attr.Val = "something"
}
}
mas como attr
não é um ponteiro, isso não funcionaria e eu tenho que fazer:
for i, attr := range n.Attr {
if attr.Key == "href" {
n.Attr[i].Val = "something"
}
}
Existe uma maneira mais simples ou mais rápida? É possível obter diretamente ponteiros range
?
Obviamente, não quero alterar as estruturas apenas para a iteração, e soluções mais detalhadas não são soluções.
Array.prototype.forEach
JavaScript?forEach
necessariamente comece com uma asserção de tipo. Isso não é realmente melhor do queattr := &n.Attr[i]
.Respostas:
Não, a abreviação que você deseja não é possível.
A razão para isso é que
range
copia os valores da fatia na qual você está repetindo. A especificação sobre a faixa diz:Portanto, o intervalo usa
a[i]
como seu segundo valor para matrizes / fatias, o que significa efetivamente que o valor é copiado, tornando o valor original intocável.Esse comportamento é demonstrado pelo seguinte código :
O código imprime locais de memória completamente diferentes para o valor do intervalo e o valor real na fatia:
Portanto, a única coisa que você pode fazer é usar ponteiros ou o índice, como já proposto por jnml e peterSO.
fonte
a[i]
loop for e oa[i]
que escrevemos? Parece a mesma coisa, mas não é, certo?range
retornaa[i]
como seu segundo valor de retorno. Esta operação,val = a[i]
conforme feita por,range
cria uma cópia do valor para que qualquer operação de gravaçãoval
seja aplicada a uma cópia.Você parece estar pedindo algo equivalente a isso:
Resultado:
Isso evita a criação de uma cópia - possivelmente grande - dos
Attribute
valores de tipo , às custas das verificações de limites de fatia. No seu exemplo, o tipoAttribute
é relativamente pequeno, com duasstring
referências de fatia: 2 * 3 * 8 = 48 bytes em uma máquina de arquitetura de 64 bits.Você também pode simplesmente escrever:
Porém, a maneira de obter um resultado equivalente com uma
range
cláusula, que cria uma cópia, mas minimiza as verificações de limites de fatia, é:fonte
value := &someMap[key]
não vai funcionar, sesomeMap
é ummap
*attr.Val = "something"
Eu adaptaria sua última sugestão e usaria a versão apenas do índice do intervalo.
Parece-me mais simples me referir
n.Attr[i]
explicitamente na linha que testaKey
e na linha que defineVal
, em vez de usarattr
para um en.Attr[i]
para o outro.fonte
Por exemplo:
Parque infantil
Resultado
Abordagem alternativa:
Parque infantil
Resultado:
fonte
go.net/html
pacote)