Rumah >pembangunan bahagian belakang >Golang >Bagaimana untuk Melepasi Struktur Bersarang melalui Rujukan dalam Refleksi dan Tetapkan Nilai Lalai Secara Rekursif?

Bagaimana untuk Melepasi Struktur Bersarang melalui Rujukan dalam Refleksi dan Tetapkan Nilai Lalai Secara Rekursif?

DDD
DDDasal
2024-10-24 02:22:29444semak imbas

How to Pass Nested Structures by Reference in Reflection and Set Default Values Recursively?

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!

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