Maison  >  Article  >  développement back-end  >  Pourquoi les appels d’interface dans mon programme Go échouent-ils ?

Pourquoi les appels d’interface dans mon programme Go échouent-ils ?

WBOY
WBOYoriginal
2023-06-10 09:18:06903parcourir

Le langage Go est devenu l'un des langages de programmation les plus populaires au monde en raison de ses caractéristiques rapides et efficaces. L'interface est une fonctionnalité puissante du langage Go, qui offre aux programmeurs un moyen très élégant d'interagir et de communiquer entre différentes structures. Cependant, lorsque les appels d’interface échouent, il s’agit d’un problème courant pour certains programmeurs débutants. Cet article explorera les raisons pour lesquelles les appels d’interface échouent et proposera des solutions.

  1. Interface sans pointeur

En langage Go, lorsque les données sont généralement transmises à une fonction, les données seront copiées dans les paramètres de la fonction. Et lorsque nous passons l'interface en paramètre à la fonction, si la valeur du type d'interface n'est pas un type pointeur, elle sera copiée en tant que type valeur. Cela peut entraîner l’échec des appels d’interface dans certains cas.

L'appel d'interface est obtenu en appelant la méthode de la valeur d'interface, et cela nécessite que le type de valeur d'interface soit un type de pointeur, car la méthode doit opérer sur le pointeur. Si nous attribuons une valeur de type non-pointeur à une interface, le langage Go copiera les données internes et créera une nouvelle valeur d'interface. Mais cette nouvelle valeur d’interface ne sera plus un type pointeur, nous ne pouvons donc pas appeler directement des méthodes sur cette nouvelle valeur d’interface. C'est pourquoi l'appel d'interface échoue.

Donc, si nous voulons appeler des interfaces et nous assurer qu'elles fonctionnent correctement, nous devons alors nous assurer que la valeur du type d'interface est un type pointeur.

  1. Incompatibilité de type d'interface

En langage Go, si une variable n'est pas un type d'interface, alors elle ne peut pas être affectée à un type d'interface. En effet, l'interface est de type dynamique et ne peut pas être vérifiée par le compilateur. Si les types d’interface ne correspondent pas, l’appel d’interface échouera également. Regardez l'exemple suivant :

type Employee struct {
    Name string
    Age  int
}

func (e Employee) ShowName() {
    fmt.Printf("Name is %s
", e.Name)
}

func showName(s interface{}) {
    s.ShowName()
}

func main() {
    emp := Employee{Name: "John", Age: 25}
    showName(emp)
}

Le code ci-dessus générera l'erreur suivante :

cannot use emp (type Employee) as type interface {} in argument to showName:
  Employee does not implement interface {} (missing ShowName method)

Le compilateur Go pensera que ce type d'employé est un type différent, il ne peut donc pas être directement affecté à une variable de type interface{}. Pour résoudre ce problème, nous pouvons modifier le type Employee pour implémenter l'interface dont il a besoin afin de pouvoir le transmettre en paramètre à la fonction showName.

  1. Implémentation incomplète de l'interface

Un autre échec d'appel d'interface courant est l'implémentation incomplète de l'interface. En bref, cela signifie que nous implémentons une interface sur un type struct, mais n'implémentons pas toutes les méthodes de l'interface. Cela peut provoquer des échecs lors des appels d'interface. Regardez l'exemple ci-dessous :

type Square struct {
    Side int
}

func (s Square) Area() int {
    return s.Side * s.Side
}

type Shape interface {
    Area() int
}

func PrintArea(s Shape) {
    fmt.Println("Area is", s.Area())
}

func main() {
    sq := Square{Side: 5}
    PrintArea(sq)
}

Le code ci-dessus produira l'erreur suivante :

cannot use sq (type Square) as type Shape in argument to PrintArea:
        Square does not implement Shape (missing Area method)

Dans cet exemple, nous avons défini un type Square et une interface Shape. Nous avons implémenté la méthode Area sur le type Square. Mais nous n'implémentons pas d'autres méthodes de l'interface Shape. Cela entraîne l’échec des appels d’interface dans la fonction PrintArea. Par conséquent, assurez-vous que toutes les méthodes de l'interface sont implémentées sur le type spécifié afin que l'appel d'interface puisse réussir.

  1. Les interfaces sont remplacées par des valeurs nulles

En langage Go, des valeurs nulles peuvent être attribuées aux interfaces. Cela signifie que dans une interface, nous pouvons transmettre une valeur nulle comme valeur valide. Cependant, cela peut également entraîner l’échec de l’appel d’interface.

Lorsque la valeur de l'interface est nulle, l'appel de méthodes dessus provoquera une erreur d'exécution. Regardez l'exemple suivant :

type Calculator interface {
    Add(a int, b int) int
}

func main() {
    var c Calculator
    fmt.Println(c.Add(1, 2))
}

Le code ci-dessus générera l'erreur suivante :

panic: runtime error: invalid memory address or nil pointer dereference

La solution est qu'avant d'utiliser une interface avec une valeur nulle, nous devons nous assurer que le type d'interface a été entièrement implémenté, ou vous pouvez utilisez une assertion de type pour déterminer que l'interface n'est pas une valeur nulle.

func main() {
    var c Calculator
    if c != nil {
        fmt.Println(c.Add(1, 2))
    }
}
  1. Séquence d'appels d'interface

Dans le langage Go, lorsque nous attribuons une valeur de type non-pointeur à l'interface, Go copiera les données internes et créera une nouvelle valeur d'interface. Cette nouvelle valeur d'interface est également une interface différente avec la même valeur. Par conséquent, lorsque nous appelons une méthode dans une interface, nous devons effectuer l’appel de méthode en dehors de l’interface avec une valeur de type primitif ou un type pointeur vers une valeur primitive.

Regardez l'exemple suivant :

type Employee struct {
    Name string
    Age  int
}

func (e Employee) ShowName() {
    fmt.Printf("Name is %s
", e.Name)
}

type NameShower interface {
    ShowName()
}

func main() {
    emp := Employee{Name: "John", Age: 25}
    var ns NameShower
    ns = emp
    ns.ShowName()

    pemp := &Employee{Name: "Doe", Age: 30}
    ns = pemp
    ns.ShowName()
}

Dans le code ci-dessus, nous définissons un type Employee et une interface NameShower. Lorsque nous créons emp et l'attribuons à ns, l'appel d'interface échouera car emp n'est pas un type pointeur vers une valeur primitive. Nous devons utiliser un pointeur vers emp pour appeler la méthode ShowName.

Lors de la création de pemp et de son attribution à ns, l'appel d'interface réussira car pemp est un type pointeur vers une valeur primitive. Assurez-vous donc que nous avons utilisé le bon type avant de passer un appel d’interface.

Conclusion

A travers cet article, nous connaissons déjà les raisons pour lesquelles les appels d'interface échouent dans les programmes Go. Ensuite, résumons :

  • Assurez-vous d'attribuer des valeurs de type pointeur aux interfaces.
  • Assurez-vous que toutes les méthodes de l'interface sont implémentées sur le type spécifié.
  • Assurez-vous que la valeur avant d'appeler l'interface n'est pas nulle, ou utilisez une assertion de type pour déterminer que l'interface n'est pas une valeur nulle.
  • Si nous utilisons des valeurs de type non-pointeur pour les appels de méthode dans l'interface, assurez-vous d'utiliser le type correct.

Si vous suivez la méthode ci-dessus, l'appel d'interface dans votre programme Go n'échouera pas.

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!

Déclaration:
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