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.
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)) } } }
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)) }
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{} }
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!