## Mengapa Menyalin Contoh Jenis Go dengan Kaedah Penerima Penunjuk Berbahaya?

Linda Hamilton
Lepaskan: 2024-10-25 10:54:30
asal
201 orang telah melayarinya

## Why is Copying Instances of Go Types with Pointer Receiver Methods Dangerous?

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
}
Salin selepas log masuk

Dengan kaedah Set() untuk memastikan kedua-dua medan mengandungi nilai yang sama:

func (w *Wrapper) Set(v int) {
    w.v = v
    *w.p = v
}
Salin selepas log masuk

Jika kita mencipta contoh Wrapper:

a := Wrapper{v: 0, p: new(int)}
Salin selepas log masuk

Dan seterusnya membuat salinan (b) a:

b := a
Salin selepas log masuk

Selepas menetapkan a kepada 1 menggunakan Set():

a.Set(1)
Salin selepas log masuk

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)
Salin selepas log masuk

Output:

a.v=1, a.p=1;  b.v=0, b.p=1
Salin selepas log masuk

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!

sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!