Maison >développement back-end >Golang >Quel est le raisonnement derrière l'approche « affirmation de type » de Go ?

Quel est le raisonnement derrière l'approche « affirmation de type » de Go ?

王林
王林avant
2024-02-06 08:12:07970parcourir

Go 的“类型断言”方式背后的原因是什么?

Contenu de la question

J'essaie de comprendre le fait que les assertions de type de Golang ne s'appliquent qu'aux variables explicitement définies comme types d'interface, pas aux types concrets (c'est-à-dire "string", "int32"), etc... ).

Voici un exemple de code simple et rapide qui illustre la cause profonde de ma confusion :

package main

import "fmt"

// here we define an interface type:
type Shape interface {
    DoubleSize() int32
}

// here we define a new type which is really just an int32:
type Rect int32

// here we make "Rect" type above comply with the "Shape" interface by implementing the methods of that interface
// and so, since the interfaces in Go are implemented implicitly, this should make the "Rect" type an implicit instance of the "Shape" interface
func (theShape Rect) DoubleSize() int32 {
    return int32(theShape) * 2
}

// this function expects its "someShape" parameter to be of "Shape" type (or "the type that quacks like "Shape" interface does))
func whateverFunction(someShape Shape) int32 {
    return someShape.DoubleSize()
}

func main() {
    var newRect = Rect(5)
    // ^^ if this is instead written as "var newRect Shape = Rect(5)" no error with type assertion happens down the line

    whateverFunction(newRect) // the function works just fine because "newRect" implicitly implements the "Shape" interface — the one that this function expects to receive.  

    // !! but type assertion doesn't work on "newRect"
    v, ok := newRect.(Shape) // error: invalid operation: newRect (variable of type Rect) is not an interface
    if !ok {
        fmt.Println("type assertion failed")
        return
    }
    fmt.Println("This is v:", v)
}
Comme le titre de cette question le suggère, je n'arrive pas à comprendre le raisonnement derrière l'implémentation des assertions de type uniquement pour les types d'interface et la vérification si la valeur sous-jacente attribuée à une variable qui implémente explicitement cette interface est la valeur que nous avons spécifiée en interne. méthode d'assertion. Cela me fait penser que « assertion de type » est un abus de langage involontaire, ce qui signifie qu'elle s'applique à tous les types mais pas uniquement aux types d'interface.

Je veux dire, il doit évidemment y avoir une raison derrière cette décision de conception du langage, et je pense que cela pourrait avoir quelque chose à voir avec la manière idiomatique d'écrire Golang, mais même si j'ai vu des tonnes de ressources sur cette question, elles n'ont jamais été publiées. préciser pourquoi.

La raison pour laquelle cela a du sens pour moi est que si un programme go devrait "mieux (je suppose, puisque la définition explicite de l'interface est facultative)" écrit avec toutes les variables représentant une interface (comportement), définissez donc un Pour des raisons de clarté et de lisibilité, explicite les interfaces sur les variables ont du sens.

Mais comme je l'ai mentionné, je n'ai jamais vu de ressource expliquant spécifiquement pourquoi la fonctionnalité "assertion de type" est implémentée dans go, et j'espère que vous pourrez m'aider à dissiper cette confusion.

-- mise à jour 1 - Ajout de contenu pour clarifier ma question :

Je pense que ma question principale concerne la raison (que je ne comprends pas) pour laquelle l'assertion de type ne fonctionne que lorsque l'interface de la variable est implémentée explicitement et non lorsque l'interface est implémentée implicitement.

Comme le démontre "whateverfunction", le code considère "newrect" pour implémenter l'interface "shape", ou "être une implémentation de l'interface "shape"" (sinon la fonction ne serait pas applicable à la variable, mais c'est le cas), mais le code derrière la méthode d'assertion de type ".(t)" ne traite pas "newrect" comme une implémentation de l'interface "shape".

Donc, s'il existe des différences dans les considérations concernant la mise en œuvre de l'interface dans Golang, je pense qu'il doit y avoir une raison (différenciation) derrière de telles décisions de conception.

C'est pourquoi j'ai mentionné que la seule raison à laquelle je peux penser jusqu'à présent est s'il s'agit d'un moyen d'amener les gens à écrire du code go d'une manière ou d'une autre.


Réponse correcte


Vous pouvez consulter la réponse de Burak Serdar - vous la trouverez peut-être plus concise et utile. Je publierai quand même l'intégralité de la chaîne de raisonnement qui a finalement fait "clic" pour moi :

|-> Les interfaces sont utilisées lorsque nous ne sommes pas sûrs du type exact de données que nous espérons recevoir (car, par exemple, le même paramètre dans une fonction d'un programme peut recevoir différents types de données à la suite d'une saisie de l'utilisateur. ), Mais nous connaissons le comportement exact que devraient avoir les données fournies.

^^ Par conséquent, le type réel de la valeur stockée dans l'interface n'est pas connu au moment de la compilation. (Sinon, évidemment, nous le préciserions dans le code.)

| -> Ainsi, nous obtenons des assertions de type pour pouvoir définir le comportement du programme en termes de valeurs possibles que nous attendons du programme lors de son exécution.

|-> Par conséquent, les assertions de type s'appliquent uniquement aux variables explicitement spécifiées comme type d'interface, et non aux variables qui peuvent implémenter la même interface mais ne sont pas explicitement spécifiées comme type d'interface

parce que

Lorsque nous utilisons des interfaces, nous n'avons besoin de cette assertion de type qu'au moment de l'exécution car nous ne connaissons pas le type exact de données qui seront envoyées au programme. Cette assertion de type n'est nécessaire que lors de l'utilisation d'interfaces, donc les assertions de type ne s'appliquent qu'au type A. qui est explicitement spécifié comme type d'interface car dans tous les autres cas, le type de données est connu (permettant au compilateur de supposer implicitement que la variable implémente l'interface - puisqu'elle connaît déjà tous les types de données des données impliquées), nous ne le faisons tout simplement pas Les assertions de type sont requises pour les données de types connus.

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:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer