Rumah  >  Artikel  >  pembangunan bahagian belakang  >  ## Mengapa Menyalin Contoh Jenis Go dengan Kaedah Penerima Penunjuk Berbahaya?

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

Linda Hamilton
Linda Hamiltonasal
2024-10-25 10:54:30185semak imbas

## 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
}

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!

Kenyataan:
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