Misalkan saya memiliki tipe-tipe ini:
type Attribute struct {
Key, Val string
}
type Node struct {
Attr []Attribute
}
dan bahwa saya ingin beralih pada atribut simpul saya untuk mengubahnya.
Saya ingin sekali dapat melakukan:
for _, attr := range n.Attr {
if attr.Key == "href" {
attr.Val = "something"
}
}
tetapi karena attr
bukan sebuah pointer, ini tidak akan berhasil dan harus saya lakukan:
for i, attr := range n.Attr {
if attr.Key == "href" {
n.Attr[i].Val = "something"
}
}
Apakah ada cara yang lebih sederhana atau lebih cepat? Apakah mungkin untuk mendapatkan pointer secara langsung range
?
Jelas saya tidak ingin mengubah struktur hanya untuk iterasi dan solusi yang lebih verbal bukanlah solusi.
Array.prototype.forEach
JavaScript?forEach
akan dimulai dengan pernyataan jenis. Itu tidak benar-benar lebih baik daripadaattr := &n.Attr[i]
.Jawaban:
Tidak, singkatan yang Anda inginkan tidak mungkin.
Alasannya adalah karena
range
menyalin nilai dari slice yang Anda iterasi. The spesifikasi tentang berbagai mengatakan:Jadi, rentang menggunakan
a[i]
sebagai nilai kedua untuk array / irisan, yang secara efektif berarti bahwa nilai tersebut disalin, membuat nilai asli tidak tersentuh.Perilaku ini ditunjukkan oleh kode berikut :
Kode ini mencetak lokasi memori yang sama sekali berbeda untuk nilai dari rentang dan nilai aktual di slice:
Jadi satu-satunya hal yang dapat Anda lakukan adalah menggunakan pointer atau indeks, seperti yang telah diusulkan oleh jnml dan peterSO.
sumber
a[i]
dari untuk loop dana[i]
saat kita menulis? Sepertinya hal yang sama tetapi tidak, kan?range
kembalia[i]
sebagai nilai pengembalian kedua. Operasi inival = a[i]
,, seperti yang dilakukan olehrange
membuat salinan nilai sehingga operasi penulisan apa punval
diterapkan ke salinan.Anda tampaknya meminta sesuatu yang setara dengan ini:
Keluaran:
Ini menghindari pembuatan - kemungkinan besar - salinan
Attribute
nilai tipe , dengan mengorbankan pengecekan slice bounds. Dalam contoh Anda, tipeAttribute
relatif kecil, duastring
referensi slice: 2 * 3 * 8 = 48 byte pada mesin arsitektur 64-bit.Anda juga bisa menulis:
Tapi, cara untuk mendapatkan hasil yang setara dengan
range
klausa, yang membuat salinan tetapi meminimalkan cek batas slice, adalah:sumber
value := &someMap[key]
tidak akan bekerja jikasomeMap
adalahmap
*attr.Val = "something"
Saya akan menyesuaikan saran terakhir Anda dan menggunakan versi rentang indeks saja.
Tampaknya lebih mudah bagi saya untuk merujuk
n.Attr[i]
secara eksplisit di kedua baris yang mengujiKey
dan baris yang mengaturVal
, daripada menggunakanattr
untuk satu dann.Attr[i]
untuk yang lain.sumber
Sebagai contoh:
Tempat bermain
Keluaran
Pendekatan alternatif:
Tempat bermain
Keluaran:
sumber
go.net/html
paket)