Supongamos que tengo estos tipos:
type Attribute struct {
Key, Val string
}
type Node struct {
Attr []Attribute
}
y que quiero iterar sobre los atributos de mi nodo para cambiarlos.
Me hubiera encantado poder hacer:
for _, attr := range n.Attr {
if attr.Key == "href" {
attr.Val = "something"
}
}
pero como attrno es un puntero, esto no funcionaría y tengo que hacer:
for i, attr := range n.Attr {
if attr.Key == "href" {
n.Attr[i].Val = "something"
}
}
¿Hay una manera más simple o más rápida? ¿Es posible obtener directamente punteros range?
Obviamente no quiero cambiar las estructuras solo por la iteración y las soluciones más detalladas no son soluciones.

Array.prototype.forEachJavaScript?forEachnecesariamente comenzaría con una aserción de tipo. Eso no es realmente mejor queattr := &n.Attr[i].Respuestas:
No, la abreviatura que desea no es posible.
La razón de esto es que
rangecopia los valores del segmento sobre el que está iterando. La especificación sobre el rango dice:Por lo tanto, el rango utiliza
a[i]como su segundo valor para matrices / sectores, lo que significa que el valor se copia, haciendo que el valor original sea intocable.Este comportamiento se demuestra mediante el siguiente código :
El código le imprime ubicaciones de memoria completamente diferentes para el valor del rango y el valor real en el segmento:
Entonces, lo único que puede hacer es usar punteros o el índice, como ya lo propusieron jnml y peterSO.
fuente
a[i]el for loop y ela[i]mientras escribimos? Parece lo mismo pero no lo es, ¿verdad?rangeregresaa[i]como su segundo valor de retorno. Esta operación,val = a[i]como se hace mediante,rangecrea una copia del valor, de modo que cualquier operación de escrituravalse aplica a una copia.Parece que estás pidiendo algo equivalente a esto:
Salida:
Esto evita crear una copia, posiblemente grande, de los
Attributevalores de tipo , a expensas de las comprobaciones de los límites de corte. En su ejemplo, el tipoAttributees relativamente pequeño, dosstringreferencias de segmento: 2 * 3 * 8 = 48 bytes en una máquina de arquitectura de 64 bits.También podrías simplemente escribir:
Pero, la forma de obtener un resultado equivalente con una
rangecláusula, que crea una copia pero minimiza las comprobaciones de los límites de corte, es:fuente
value := &someMap[key]no funcione sisomeMapes unmap*attr.Val = "something"Adaptaría su última sugerencia y usaría la versión de rango de solo índice.
Me parece más simple referirme
n.Attr[i]explícitamente tanto en la línea que pruebaKeycomo en la línea que estableceVal, en lugar de usarattrpara una yn.Attr[i]para la otra.fuente
Por ejemplo:
Patio de recreo
Salida
Enfoque alternativo:
Patio de recreo
Salida:
fuente
go.net/htmlpaquete)