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
Mary-Kate Olsenoriginal
2024-12-11 09:54:14412parcourir

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++
  }
}

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) }()

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) }()

    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)

    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)

    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)

    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!

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