Gunakan pantulan untuk mengulang struktur secara rekursif dan tetapkan medan

WBOY
Lepaskan: 2024-02-10 20:45:10
ke hadapan
585 orang telah melayarinya

Gunakan pantulan untuk mengulang struktur secara rekursif dan tetapkan medan

Dalam artikel ini, editor PHP Xigua akan memperkenalkan cara menggunakan refleksi untuk mengulang struktur secara rekursif dan menetapkan medan. Refleksi ialah ciri berkuasa dalam PHP yang membolehkan kami memperoleh dan memanipulasi maklumat seperti kelas, kaedah, sifat, dll. pada masa jalan. Struktur lelaran rekursif ialah kaedah pemprosesan biasa, yang boleh membantu kami merentasi dan mengendalikan struktur data yang kompleks. Dengan menggabungkan pantulan dan struktur lelaran rekursif, kita boleh mendapatkan dan menetapkan nilai medan dengan mudah, membolehkan pengaturcaraan yang lebih fleksibel dan cekap. Dalam kandungan berikut, kami akan memperkenalkan proses ini secara terperinci untuk membantu pembaca memahami dan menggunakan teknik ini dengan lebih baik.

Kandungan soalan

Saya ingin membina program yang menggunakan refleksi untuk menetapkan medan struktur. Saya membuatnya berfungsi untuk medan peringkat atas, tetapi saya bergelut dengan medan struct bersarang. Bagaimana untuk mengulangi medan struct bersarang?

type Payload struct {
    Type    string   `json:"type"`
    SubItem *SubItem `json:"sub_item"`
}

type SubItem struct {
    Foo string `json:"foo"`
}

func main() {
    var payload Payload
    setValue(&payload, "type", "test1")
    setValue(&payload, "sub_item.foo", "test2")
}

func setValue(structPtr interface{}, key string, value string) {
    structValue := reflect.Indirect(reflect.ValueOf(structPtr))
    for i, subkey := range strings.Split(key, ".") {
        isLast := i == len(strings.Split(key, "."))-1
        var found bool
        // this line is crashing with "reflect: call of reflect.Value.NumField on zero Value"
        for i := 0; i < structValue.NumField(); i++ {
            field := structValue.Type().Field(i)
            jsonTags := strings.Split(field.Tag.Get("json"), ",")
            if jsonTags[0] == subkey {
                found = true
                if isLast {
                    if isLast {
                        // last element
                        // TODO set value
                        fmt.Printf("TODO set value %s to %v", value, structValue)
                        structValue = reflect.Indirect(reflect.ValueOf(structPtr))
                    }
                } else {
                    structValue = reflect.Indirect(reflect.ValueOf(structValue.Field(i).Interface()))
                }
                break
            }
        }
        if !found {
            panic(fmt.Errorf("failed to find field %s", key))
        }
    }
}
Salin selepas log masuk

Penyelesaian

Gunakan ciri ini:

func setvalue(p interface{}, key string, value interface{}) {
    v := reflect.valueof(p)

    // loop through the names in key to find the target field.
    for _, name := range strings.split(key, ".") {

        // if the value is pointer, then
        // - allocate value if ptr is nil.
        // - indirect ptr
        for v.kind() == reflect.ptr {
            if v.isnil() {
                v.set(reflect.new(v.type().elem()))
            }
            v = v.elem()
        }

        // we expect that the value is struct. find the 
        // named field.
        v = findjsonfield(v, name)
        if !v.isvalid() {
            panic(fmt.sprintf("could not find field %s", key))
        }
    }
    
    // set the field.
    v.set(reflect.valueof(value))
}
Salin selepas log masuk

Fungsi findjsonfield mencari medan struktur melalui tag json medan:

func findJSONField(v reflect.Value, name string) reflect.Value {
    t := v.Type()
    for i := 0; i < v.NumField(); i++ {
        if tag, _, _ := strings.Cut(t.Field(i).Tag.Get("json"), ","); tag == name {
            return v.Field(i)
        }
    }
    return reflect.Value{}
}
Salin selepas log masuk

https://www.php.cn/link/e4848ea6b69df2c66c87e2877e74726b

Atas ialah kandungan terperinci Gunakan pantulan untuk mengulang struktur secara rekursif dan tetapkan medan. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:stackoverflow.com
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
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!