Menambah pada Go Slice dengan Refleksi: Mendedahkan Isu Tersembunyi
Apabila menambahkan elemen baharu pada kepingan menggunakan pakej pantulan Go, tingkah laku yang tidak dijangka mungkin timbul di mana kepingan asal kekal tidak terjejas. Ini jelas dalam coretan kod berikut:
func appendToSlice(arrPtr interface{}) { valuePtr := reflect.ValueOf(arrPtr) value := valuePtr.Elem() value = reflect.Append(value, reflect.ValueOf(55)) fmt.Println(value.Len()) // prints 1 } func main() { arr := []int{} appendToSlice(&arr) fmt.Println(len(arr)) // prints 0 }
Walaupun menambahkan elemen pada nilai yang dihiris, kepingan asal mengekalkan panjang asalnya sifar. Percanggahan yang membingungkan ini memerlukan sedikit penjelasan.
Refleksi dan Operasi Slice
Refleksi membolehkan kami memeriksa dan memanipulasi struktur data pada masa jalan, termasuk kepingan. Fungsi reflect.Append, serupa dengan append, mengambil nilai hirisan dan elemen baharu dan mengembalikan nilai hirisan baharu yang mengandungi elemen yang dikemas kini. Walau bagaimanapun, operasi ini tidak mengubah suai rujukan hirisan asal.
Dalam kod yang disediakan, pernyataan reflect.Append memberikan pantulan baharu. Nilai kepada pembolehubah nilai, menggantikan rujukan asal kepada hirisan dengan berkesan. Semasa nilai itu sendiri dikemas kini, penuding arr asal kekal tidak berubah, oleh itu panjang hirisan arr yang tidak diubah dalam fungsi utama.
Mengemas kini Slice Asal
Kepada kemas kini kepingan asal, kita perlu menggunakan kaedah Value.Set. Kaedah ini menggantikan nilai pada indeks yang ditentukan dalam nilai yang dihiris dengan nilai baharu. Dalam kes kami, kami perlu menggantikan keseluruhan kepingan dengan nilai baharu yang dikembalikan oleh reflect.Lampirkan:
func appendToSlice(arrPtr interface{}) { valuePtr := reflect.ValueOf(arrPtr) value := valuePtr.Elem() value.Set(reflect.Append(value, reflect.ValueOf(55))) fmt.Println(value.Len()) // prints 1 }
Dengan pengubahsuaian ini, kepingan asal kini dikemas kini seperti yang ditunjukkan dalam output.
Kesimpulan
Melampirkan pada kepingan menggunakan pantulan memerlukan nuansa yang lebih sedikit daripada operasi tambah konvensional. Perkara utama ialah operasi pantulan berfungsi dengan salinan nilai dan untuk mengemas kini nilai asal, seseorang mesti menetapkannya secara eksplisit menggunakan kaedah Value.Set.
Atas ialah kandungan terperinci Mengapa `reflect.Append` Reflection tidak mengubah suai Go Slice Asal?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!