web-dev-qa-db-fra.com

Pourquoi l'interface ne peut-elle pas être implémentée avec des récepteurs de pointeurs

Je ne comprends pas pourquoi cela ne se compile pas avec:

assertion de type impossible: Faz n'implémente pas Foo (la méthode Bar a un récepteur de pointeur)

si je fais du récepteur pour Faz.Bar une valeur Faz plutôt qu'un pointeur Faz alors il se compile bien, mais j'ai pensé qu'il était toujours préférable d'avoir des récepteurs de pointeur pour que les valeurs ne soient pas copiées?

package main

import (
    "log"
)

func main() {
    foo := New().(Faz)
    log.Println(foo)
}

type Foo interface {
    Bar() string
}

func New() Foo {
    return &Faz{}
}

type Faz struct {
}

func (f *Faz) Bar() string {
    return `Bar`
}
51
Daniel Robinson

Parce que c'est *Faz pas Faz.

func main() {
    foo := New().(*Faz)
    log.Println(foo)
}
52
OneOfOne

Je pense que la réponse à cette question nécessite une approche plus rétrospective de la grammaire et comment la mettre en œuvre à travers le génie logiciel. (Excusez la simplification excessive)


D'abord un flashback rapide de ce que sont types?
Ce ne sont que des blocs de mémoire avec la logique du compilateur en haut. Ce qui rend un array différent d'un string, c'est ce que le compilateur nous permet de faire avec ces blocs de mémoire. (Pensez plus profondément et vous pourrez commencer à réaliser la vraie différence entre les langues strongly typed Et dynamically typed.)

Maintenant, vous devez vous rendre compte que les pointeurs sont leurs propres types.
*variable Est un bloc de mémoire (type aka) différent de variable. C'est juste que le compilateur suppose toujours que le contenu de *variable Sera toujours une adresse vers un bloc de mémoire de type à droite de la déclaration avec d'autres restrictions/fonctionnalités qu'il impose.

Récapitulons ensuite ce qu'est une interface.
Définition pseudo-scientifique : Un ensemble d'exigences pour tout citoyen de première classe pour être d'un type spécifique. Traduit en génie logiciel - tout bloc de mémoire (types) qui a la même structure de mémoire (repensez à emballage de la structure) associé à celui-ci comme décrit dans un contrat (interface) peut être transmis comme avec le nom de type que le contrat mentionne.


Vous pouvez maintenant commencer à réaliser que lorsque vous dites

func (f *Faz) Bar() string est le bloc de mémoire de f contenant une fonction, où le type de f est un pointeur vers Faz

où les zones

func (f Faz) Bar() string est le bloc de mémoire de f, où le type de f est Faz

Ainsi, lorsque vous dites qu'une variable de type *Faz Satisfait un contrat, comment pouvez-vous supposer qu'une variable de type Faz sera qualifiée de type d'interface dans le code? Choisissez qui satisfait votre contrat et seul ce type peut assumer le type d'interface dans votre code.

4
dtx