Verwenden Sie Reflection, um eine Struktur rekursiv zu durchlaufen und Felder festzulegen

WBOY
Freigeben: 2024-02-10 20:45:10
nach vorne
584 Leute haben es durchsucht

Verwenden Sie Reflection, um eine Struktur rekursiv zu durchlaufen und Felder festzulegen

Der PHP-Editor Xigua stellt in diesem Artikel vor, wie man die Reflexionsrekursion zum Iterieren der Struktur und zum Festlegen von Feldern verwendet. Reflection ist eine leistungsstarke Funktion in PHP, die es uns ermöglicht, Informationen wie Klassen, Methoden, Eigenschaften usw. zur Laufzeit abzurufen und zu bearbeiten. Die rekursive Iterationsstruktur ist eine gängige Verarbeitungsmethode, die uns beim Durchlaufen und Betreiben komplexer Datenstrukturen helfen kann. Durch die Kombination von Reflexions- und rekursiven Iterationsstrukturen können wir den Wert eines Felds einfach ermitteln und festlegen, was eine flexiblere und effizientere Programmierung ermöglicht. Im folgenden Inhalt stellen wir diesen Prozess im Detail vor, um den Lesern zu helfen, diese Technik besser zu verstehen und anzuwenden.

Frageninhalt

Ich möchte ein Programm erstellen, das mithilfe von Reflektion die Felder einer Struktur festlegt. Ich habe es für Felder der obersten Ebene zum Laufen gebracht, aber ich habe Probleme mit verschachtelten Strukturfeldern. Wie iteriere ich über verschachtelte Strukturfelder?

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))
        }
    }
}
Nach dem Login kopieren

Workaround

Verwenden Sie diese Funktion:

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))
}
Nach dem Login kopieren

Die Funktion findjsonfield findet das Strukturfeld über das JSON-Tag des Feldes:

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{}
}
Nach dem Login kopieren

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

Das obige ist der detaillierte Inhalt vonVerwenden Sie Reflection, um eine Struktur rekursiv zu durchlaufen und Felder festzulegen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:stackoverflow.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!