Dans cet article, l'éditeur PHP Xigua présentera comment utiliser la réflexion pour itérer la structure de manière récursive et définir les champs. La réflexion est une fonctionnalité puissante de PHP qui nous permet d'obtenir et de manipuler des informations telles que des classes, des méthodes, des propriétés, etc. au moment de l'exécution. La structure itérative récursive est une méthode de traitement courante, qui peut nous aider à parcourir et à exploiter des structures de données complexes. En combinant des structures de réflexion et d'itération récursive, nous pouvons facilement obtenir et définir la valeur d'un champ, permettant une programmation plus flexible et plus efficace. Dans le contenu suivant, nous présenterons ce processus en détail pour aider les lecteurs à mieux comprendre et appliquer cette technique.
Je souhaite construire un programme qui utilise la réflexion pour définir les champs d'une structure. Je l'ai fait fonctionner pour les champs de niveau supérieur, mais j'ai du mal avec les champs de structure imbriqués. Comment parcourir des champs de structure imbriqués ?
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)) } } }
Utilisez cette fonctionnalité :
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)) }
La fonction findjsonfield trouve le champ de structure grâce à la balise json du champ :
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
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!