Rumah >pembangunan bahagian belakang >Golang >## Mengapa Menyalin Contoh Jenis Go dengan Kaedah Penerima Penunjuk Berbahaya?
Kesalahan Menyalin Kejadian dengan Kaedah Penerima Penunjuk
Dalam Go, jika semua kaedah untuk jenis T yang dinamakan mempunyai jenis penerima T itu sendiri (bukan *T), menyalin contoh jenis itu dianggap selamat. Ini kerana sebarang panggilan kaedah semestinya beroperasi pada salinan, memastikan bahawa nilai asal kekal tidak diubah suai. Walau bagaimanapun, jika mana-mana kaedah untuk T mempunyai penerima penunjuk, menyalin contoh T boleh berbahaya.
Penjelasan
Apabila memanggil kaedah, nilai kaedah digunakan pada mula-mula disalin, dan salinan itu dihantar sebagai penerima. Jika jenis hanya mempunyai kaedah dengan penerima nilai, ia menjamin bahawa kaedah tidak boleh mengubah suai nilai asal, tanpa mengira tindakannya. Ini kerana salinan sentiasa digunakan, melindungi yang asal daripada pengubahsuaian yang tidak disengajakan.
Walau bagaimanapun, jika sesuatu jenis mempunyai kaedah dengan penerima penunjuk, kaedah tersebut boleh mengubah suai nilai bertitik asal dan bukannya salinannya. Ini kerana kaedah menerima penunjuk kepada nilai asal, membenarkannya mengubah data asas.
Contoh
Pertimbangkan jenis pembalut:
type Wrapper struct { v int p *int }
Dengan kaedah Set() untuk memastikan kedua-dua medan mengandungi nilai yang sama:
func (w *Wrapper) Set(v int) { w.v = v *w.p = v }
Jika kita mencipta contoh Wrapper:
a := Wrapper{v: 0, p: new(int)}
Dan seterusnya membuat salinan (b) a:
b := a
Selepas menetapkan a kepada 1 menggunakan Set():
a.Set(1)
Kami menjangkakan kedua-dua a dan b mempunyai medan mereka ditetapkan kepada 1. Walau bagaimanapun, mencetak nilai mereka mendedahkan cerita yang berbeza:
fmt.Printf("a.v=%d, a.p=%d; b.v=%d, b.p=%d\n", a.v, *a.p, b.v, *b.p)
Output:
a.v=1, a.p=1; b.v=0, b.p=1
Sebab bagi percanggahan ini ialah walaupun penunjuk dalam b disalin, ia masih merujuk perkara yang sama data asas sebagai penunjuk dalam a. Apabila Set() mengubah suai nilai yang ditunjuk, ia mempengaruhi kedua-dua salinan Wrapper. Walau bagaimanapun, medan bukan penunjuk v kekal berbeza antara a dan b.
Amalan Terbaik
Untuk mengelakkan isu ini, adalah disyorkan untuk mengelak daripada menyalin contoh jenis dengan kaedah penerima penunjuk. Jika bekerja dengan nilai penunjuk adalah perlu, menyalin penunjuk itu sendiri (*T) ialah alternatif yang berdaya maju.
Atas ialah kandungan terperinci ## Mengapa Menyalin Contoh Jenis Go dengan Kaedah Penerima Penunjuk Berbahaya?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!