Maison > développement back-end > Golang > Comment appeler dynamiquement des méthodes sur `interface{}` dans Go, quel que soit le type de récepteur ?

Comment appeler dynamiquement des méthodes sur `interface{}` dans Go, quel que soit le type de récepteur ?

DDD
Libérer: 2024-12-26 20:04:22
original
604 Les gens l'ont consulté

How to Dynamically Invoke Methods on `interface{}` in Go, Regardless of Receiver Type?

Invocation dynamique de méthodes sur l'interface{} Quel que soit le type de récepteur

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.

Le problème

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.

La solution

Pour résoudre ce problème, nous exploitons une technique qui englobe quatre cas :

  1. Les données d'interface{} sont une valeur, le récepteur est une valeur : Dans ce cas, aucune modification n'est nécessaire.
  2. Les données d'interface{} sont un pointeur, le récepteur est une valeur : Nous créons un nouveau pointeur vers les données d'interface{} et récupérons la valeur référencée.
  3. Les données de l'interface{} sont une valeur, le récepteur est un pointeur : Nous créons un nouveau pointeur vers l'interface{} data.
  4. Interface{} data est un pointeur, le récepteur est un pointeur : Nous utilisons le pointeur existant.

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.

Preuve de concept

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"))
}
Copier après la connexion

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!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal