Maison > développement back-end > Golang > Comment utiliser correctement « defer » dans Go avec des variables modifiées ?

Comment utiliser correctement « defer » dans Go avec des variables modifiées ?

Mary-Kate Olsen
Libérer: 2024-12-11 09:54:14
original
418 Les gens l'ont consulté

How to Correctly Use `defer` in Go with Modified Variables?

Clarification de l'utilisation du report

Dans Go, l'instruction "defer" nous permet de planifier l'exécution d'une fonction juste avant le retour de la fonction environnante. Cependant, cela peut prêter à confusion lorsqu'il s'agit de variables modifiées dans la fonction englobante.

Problème original

Considérez la fonction suivante :

func printNumbers() {
  var x int

  defer fmt.Println(x)

  for i := 0; i < 5; i++ {
    x++
  }
}
Copier après la connexion

Selon le Spécification Go, lorsqu'une instruction "defer" est exécutée, la valeur de la fonction et les paramètres sont évalués et stockés pour une exécution ultérieure. Cela signifie que lorsque la fonction sera finalement appelée, la valeur de x sera toujours 0 car elle a été évaluée au moment du report.

Solution avec fonction anonyme

Pour résoudre ce problème, nous peut utiliser une fonction anonyme dans l'instruction "defer":

defer func() { fmt.Println(x) }()
Copier après la connexion

Ici, x n'est pas un paramètre de la fonction anonyme, il ne sera donc pas évalué lorsque le L'instruction "defer" est exécutée. Au lieu de cela, la valeur de x sera capturée au moment où la fonction anonyme est appelée, garantissant que la valeur la plus à jour est imprimée.

Solutions alternatives

  1. Utilisation d'un pointeur :

    var x int
    
    defer func() { fmt.Println(&x) }()
    Copier après la connexion

    Cette approche utilise un pointeur vers x comme paramètre du différé fonction. Lorsque l'instruction "defer" est exécutée, seul le pointeur est évalué, pas la valeur de x. Lorsque la fonction différée est appelée, elle accédera à la valeur actuelle de x via le pointeur.

  2. Utilisation d'un type personnalisé :

    type MyInt int
    
    func (m *MyInt) String() string {
      return strconv.Itoa(int(*m))
    }
    
    var x MyInt
    
    defer fmt.Println(&x)
    Copier après la connexion

    Cette solution est similaire à l'approche pointeur mais utilise un type personnalisé (MyInt) qui implémente la méthode String(). En implémentant String(), nous pouvons contrôler la façon dont la valeur de x est imprimée.

  3. Utiliser une tranche :

    var x []int
    
    defer fmt.Println(x)
    Copier après la connexion

    Le découpage est un type de descripteur en Go, ce qui signifie que sa valeur est une référence à un tableau sous-jacent. Lorsque nous différons une tranche, seule la référence est évaluée, pas les éléments réels du tableau. Par conséquent, toutes les modifications apportées aux éléments de tranche après le report seront reflétées dans la sortie imprimée.

  4. Enveloppement dans une structure :

    type Wrapper struct {
      Value int
    }
    
    var x Wrapper
    
    defer fmt.Println(&x)
    Copier après la connexion

    Cette approche est similaire à l'utilisation d'un pointeur, mais nous enveloppons la valeur dans une structure pour éviter d'avoir à déréférencer le pointeur dans le différé fonction.

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
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal