Rumah >pembangunan bahagian belakang >Golang >Bagaimana untuk Melepasi Struktur Bersarang melalui Rujukan dalam Refleksi dan Tetapkan Nilai Lalai Secara Rekursif?
Melalui Struktur Bersarang melalui Rujukan melalui Refleksi
Merentasi dan mengubah suai struktur bersarang melalui pantulan membolehkan manipulasi data yang dinamik. Walau bagaimanapun, apabila menemui medan struct yang merupakan struct itu sendiri, menetapkan nilai menggunakan pantulan boleh membawa kepada panik "reflect.Value.Set menggunakan nilai tidak boleh ditangani".
Memahami Isu
Punca masalah terletak pada cara pantulan mengendalikan struktur bersarang. Secara lalai, struct diluluskan mengikut nilai, yang bermaksud apabila kami mendapatkan semula Nilai daripada medan struct bersarang untuk pengubahsuaian, kami beroperasi pada salinan data dan bukannya asal. Sebarang perubahan yang dibuat hanya menjejaskan salinan, bukan struktur sebenar.
Penyelesaian: Melewati Rujukan
Untuk menetapkan nilai medan struct bersarang, perlu lulus ia sebagai penunjuk. Ini boleh dicapai menggunakan kaedah Value.Addr(), yang mengembalikan penunjuk kepada nilai struct sebenar.
Tetapan Nilai Lalai Rekursif
Rekursi dalam sampel kod mencerminkan keperluan untuk merentasi semua medan struct dan struct bersarangnya. Untuk menetapkan nilai lalai, kami memanggil setDefaultValue pada nilai penunjuk setiap medan. Untuk jenis primitif (int, string, bool), nilai lalai dikodkan keras. Untuk struct bersarang, setDefaultValue dipanggil secara rekursif untuk mengendalikan medannya.
Contoh Kerja
Pertimbangkan kod contoh berikut:
<code class="go">type Client struct { Id int Age int PrimaryContact Contact Name string } type Contact struct { Id int ClientId int IsPrimary bool Email string } func SetDefault(s interface{}) error { return setDefaultValue(reflect.ValueOf(s)) } func setDefaultValue(v reflect.Value) error { if v.Kind() != reflect.Ptr { return errors.New("Not a pointer value") } v = reflect.Indirect(v) switch v.Kind() { case reflect.Int: v.SetInt(42) case reflect.String: v.SetString("Foo") case reflect.Bool: v.SetBool(true) case reflect.Struct: // Iterate over the struct fields for i := 0; i < v.NumField(); i++ { err := setDefaultValue(v.Field(i).Addr()) if err != nil { return err } } default: return errors.New("Unsupported kind: " + v.Kind().String()) } return nil } func main() { a := Client{} err := SetDefault(&a) if err != nil { fmt.Println("Error: ", err) } else { fmt.Printf("%+v\n", a) } }</code>
Output:
{Id:42 Age:42 PrimaryContact:{Id:42 ClientId:42 IsPrimary:true Email:Foo} Name:Foo}
Contoh ini mempamerkan cara menghantar struktur bersarang melalui rujukan melalui pantulan, menetapkan nilai lalai menggunakan rekursi.
Atas ialah kandungan terperinci Bagaimana untuk Melepasi Struktur Bersarang melalui Rujukan dalam Refleksi dan Tetapkan Nilai Lalai Secara Rekursif?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!