Maison > développement back-end > Golang > Pourquoi mon code Go imprime-t-il « Trois » trois fois au lieu de « Un », « Deux » et « Trois » dans une course aux données Goroutine ?

Pourquoi mon code Go imprime-t-il « Trois » trois fois au lieu de « Un », « Deux » et « Trois » dans une course aux données Goroutine ?

Linda Hamilton
Libérer: 2024-12-07 22:23:13
original
908 Les gens l'ont consulté

Why Does My Go Code Print

Comprendre le comportement curieux des Goroutines dans un scénario de course aux données

Dans le code Go fourni, nous créons une tranche de champs de structure appelée données contenant les noms « un », « deux » et « trois ». Le code parcourt la tranche, créant des goroutines pour imprimer le nom de chaque champ à l'aide de la méthode d'impression. Cependant, contrairement aux attentes, le code imprime à plusieurs reprises « trois » trois fois, plutôt que la séquence prévue de « un », « deux » et « trois ».

Dévoilement de la course aux données

Ce comportement curieux découle d'une course aux données, qui se produit lorsque plusieurs goroutines accèdent et modifient potentiellement les mêmes données partagées simultanément. Dans ce cas, le problème vient de l’utilisation implicite de l’adresse de la variable range v lors de la création des goroutines. Lorsque la variable de boucle v est modifiée à chaque itération, les goroutines finissent par utiliser sa valeur finale, ce qui entraîne l'impression constante de « trois ».

Répondre à la course aux données

Pour résoudre ce problème, nous pouvons adopter plusieurs approches :

  • Créer une nouvelle variable dans chaque boucle Itération : Dans la boucle, nous pouvons déclarer une nouvelle variable avec le même nom que la variable de plage, créant ainsi une nouvelle portée pour la variable.

    for _, v := range data {
      v := v // Declare a new variable `v` within the loop scope.
      go v.print()
    }
    Copier après la connexion
  • Utiliser une tranche de pointeurs : Au lieu d'utiliser une tranche de champs de structure, nous pouvons utiliser une tranche de pointeurs vers les champs. Cela garantit que les goroutines reçoivent des pointeurs vers des éléments de champ individuels, évitant ainsi les problèmes de course aux données.

    data := []*field{ {"one"},{"two"},{"three"} }
    for _, v := range data {
      go v.print()
    }
    Copier après la connexion
  • Transmission de l'adresse de l'élément Slice : Une autre alternative consiste à transmettre l'adresse de chaque élément de la tranche au goroutine.

    for i := range data {
      v := &data[i] // Take the address of the slice element.
      go v.print()
    }
    Copier après la connexion
  • Utilisation de fonctions anonymes et transmission de variables de plage comme arguments : Si la fonction goroutine se trouve dans une fonction anonyme, nous pouvons éviter le problème en passant les variables de plage comme arguments de la fonction.

    for _, v := range data {
      go func(v field) { // Pass the range variable `v` as an argument.
          v.print()
      }(v)
    }
    Copier après la connexion

Ces approches garantissent que les goroutines ont leurs propres copies des données dont elles ont besoin, éliminant ainsi la course aux données et produisant la sortie correcte de « un », « deux » et « trois » dans n'importe quel ordre.

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