Maison > développement back-end > Golang > Pourquoi Go renvoie-t-il un pointeur vers un wrapper d'erreur mais le déclare-t-il avec 'erreur' au lieu de '*erreur'

Pourquoi Go renvoie-t-il un pointeur vers un wrapper d'erreur mais le déclare-t-il avec 'erreur' au lieu de '*erreur'

WBOY
Libérer: 2024-02-09 22:40:10
avant
593 Les gens l'ont consulté

为什么 Go 返回一个指向错误包装器的指针,但用“error”而不是“*error”声明它

Pourquoi Go renvoie-t-il un pointeur vers un wrapper d'erreur mais le déclare-t-il avec « erreur » au lieu de « erreur » ? Il s’agit d’un problème courant rencontré par de nombreux développeurs du langage Go. En termes simples, la façon dont Go renvoie les erreurs est de faciliter son utilisation et sa gestion. Dans Go, une erreur est un type d'interface doté d'une méthode Error() qui renvoie un message d'erreur. Par conséquent, lorsqu’une fonction renvoie une erreur, elle renvoie en fait un pointeur vers une structure qui implémente la méthode Error(). Cette conception rend la gestion des erreurs plus concise et flexible, réduisant ainsi la redondance et la complexité du code. Ainsi, même si renvoyer un pointeur peut sembler étrange, il est en réalité destiné à fournir une meilleure gestion des erreurs.

Contenu de la question

J'apprends le langage Go à partir d'un arrière-plan Java.

type MyError struct {
    message string
    Offset  int
}

func (Me *MyError) Error() string {
    return Me.message
}

func myFunction() (int, error) {      <-- Why the return type is "error" rather than "*error"
    return 0, &MyError{"my error message", 0} <-- The error is returned as a pointer.
}

func main() {
    var _, err = myFunction()
    if e, ok := err.(*MyError); ok {.  <-- Why I can assert err which is a type of "error" into a pointer
        fmt.Printf("Error is %s: %d\n", e.message, e.Offset)
    }
}
Copier après la connexion

Dans le code ci-dessus, je ne comprends pas pourquoi le type d'erreur de myFunction est « error » au lieu de « *error » ? Je renvoie clairement un pointeur vers la structure MyError dans la ligne ci-dessous.

Je comprends également pourquoi je peux affirmer l'erreur dans la fonction principale au pointeur.

Solution de contournement

Pour comprendre la gestion traditionnelle des erreurs dans Go, vous devez d'abord comprendre comment fonctionnent les interfaces du langage. Il y a deux choses à retenir lorsqu'on parle des interfaces Go :

  1. Une interface dans Go définit un ensemble de méthodes (commencer par Go1.18 est aussi un ensemble de types). En coulisses, les interfaces Go contiennent deux éléments, des types T 和值 VV 始终是具体类型,例如 intstruct ou des pointeurs, plutôt que l'interface elle-même.

  2. Il n'y a pas de mot-clé implements dans Go. Les types Go satisfont cette interface en implémentant ses méthodes. C’est ce qu’on appelle la mise en œuvre implicite.

Gestion des erreurs

Go définit un type error intégré, qui n'est qu'une interface :

type error interface {
    Error() string
}
Copier après la connexion

En fait, cela n’a rien de spécial, sauf que c’est un type prédéfini global. Ce type est généralement utilisé pour la gestion des erreurs.

Prenez votre exemple :

func myFunction() (int, error) {
    return 0, &MyError{"my error message", 0}
}

func main() {
    var _, err = myFunction()
    if e, ok := err.(*MyError); ok {
        fmt.Printf("Error is %s: %d\n", e.message, e.Offset)
    }
}
Copier après la connexion

La relation entre le pointeur vers MyError et l'interface MyError 的指针和 error 接口之间的关系发生在幕后,您不需要显式返回 *error 即可从 MyError 值引用 error se produit en coulisses, vous n'avez pas besoin de renvoyer explicitement *error pour obtenir la valeur de MyError Référence (En fait, vous presque jamais besoin d'un pointeur vers une interface

).

myFunction 后,error 值将保存以下元组 (V=&MyError{message: "my error message", Offset: 0}, T=*MyError),其中 V 是它的值保持,T 是值 VAprès avoir renvoyé myFunction, la valeur

enregistrera le tuple suivant (V=&MyError{message : "mon message d'erreur", Offset : 0}, T=*MyError) , Où V est sa valeur conservée et T est le type de valeur V.

e, ok := err.(*MyError) 是: err 值(哪种类型是 error 接口)是否将类型 *MyError 作为其底层 T?如果是这样,则 ok 将是 true,并且 e 将接收其底层 V&MyError{message: "我的错误消息", Offset: 0}Parce que Go vous permet de taper des assertions sur les valeurs de l'interface. Fondamentalement, ce que vous demandez à propos de l'opération Go e, ok := err.(*MyError) est : si la valeur err (quel type est l'interface

) sera de type *MyError comme son T sous-jacent ? Si tel est le cas, alors ok sera true et e recevra sa valeur V sous-jacente &MyError {message : "Mon message d'erreur", Décalage : 0}.

Remarquenil : Veuillez traiter les valeurs d'erreur avec prudence, car elles peuvent ne pas toujours se comporter comme prévu

en raison des nuances de l'interface. 🎜

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:stackoverflow.com
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