Dans cet article, nous explorons un problème rencontré lors de la tentative d'appel dynamique de méthodes sur une interface{} en Aller. Notre objectif est de surmonter ce défi, en permettant une invocation de méthode efficace quel que soit le type de données sous-jacent ou le type de récepteur.
Lorsque nous traitons de l'interface{} dans Go, nous avons rencontré une limitation dans invocation de méthode dynamique : si les données stockées dans l'interface{} étaient un pointeur, nous rencontrions des difficultés pour accéder à son adresse. Par conséquent, les méthodes avec des récepteurs de pointeurs n'ont pas pu être invoquées dynamiquement.
Pour résoudre ce problème, nous exploitons une technique qui englobe quatre cas :
Après avoir déterminé le type de données approprié, nous effectuez une vérification supplémentaire de l'existence de la méthode à la fois sur la valeur et sur le pointeur. Ce faisant, nous garantissons l'invocation de la méthode, que la méthode soit déclarée comme récepteur de valeur ou de pointeur.
Le code suivant démontre la mise en œuvre de notre solution :
package main import ( "fmt" "reflect" ) type Test struct { Start string } // value receiver func (t Test) Finish() string { return t.Start + "finish" } // pointer receiver func (t *Test) Another() string { return t.Start + "another" } func CallMethod(i interface{}, methodName string) interface{} { var ptr reflect.Value var value reflect.Value var finalMethod reflect.Value value = reflect.ValueOf(i) // if we start with a pointer, we need to get value pointed to // if we start with a value, we need to get a pointer to that value if value.Type().Kind() == reflect.Ptr { ptr = value value = ptr.Elem() } else { ptr = reflect.New(reflect.TypeOf(i)) temp := ptr.Elem() temp.Set(value) } // check for method on value method := value.MethodByName(methodName) if method.IsValid() { finalMethod = method } // check for method on pointer method = ptr.MethodByName(methodName) if method.IsValid() { finalMethod = method } if (finalMethod.IsValid()) { return finalMethod.Call([]reflect.Value{})[0].Interface() } // return or panic, method not found of either type return "" } func main() { i := Test{Start: "start"} j := Test{Start: "start2"} fmt.Println(CallMethod(i, "Finish")) fmt.Println(CallMethod(&i, "Finish")) fmt.Println(CallMethod(i, "Another")) fmt.Println(CallMethod(&i, "Another")) fmt.Println(CallMethod(j, "Finish")) fmt.Println(CallMethod(&j, "Finish")) fmt.Println(CallMethod(j, "Another")) fmt.Println(CallMethod(&j, "Another")) }
En employant cette technique, nous pouvons invoquer dynamiquement des méthodes sur l'interface{} quel que soit le type de récepteur, facilitant ainsi un code robuste et adaptable dans Go.
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!