Maison > développement back-end > Golang > Comment éviter les courses aux données lors du lancement de Goroutines dans Go ?

Comment éviter les courses aux données lors du lancement de Goroutines dans Go ?

Mary-Kate Olsen
Libérer: 2024-12-08 17:37:11
original
209 Les gens l'ont consulté

How to Avoid Data Races When Launching Goroutines in Go?

Course de données dans une routine Go simultanée

Ce code démontre un problème de course aux données dans une routine Go simultanée :

package main

import (
    "fmt"
    "time"
)

type field struct {
    name string
}

func (p *field) print() {
    fmt.Println(p.name)
}

func main() {
    data := []field{{"one"}, {"two"}, {"three"}}
    for _, v := range data {
        go v.print()
    }
    <-time.After(1 * time.Second)
}
Copier après la connexion

Problème :

Le code imprime "trois" trois fois au lieu de imprimer "un", "deux" et "trois" dans n'importe quel ordre. C'est parce qu'il y a une course aux données.

Explication :

Implicitement, le code prend l'adresse de la variable v lors de l'évaluation des arguments de la fonction goroutine. La fonction goroutine v.print() est équivalente à (&v).print(). La boucle change la valeur de v, et lorsque les goroutines s'exécutent, elles ont la dernière valeur de la boucle ("trois").

Corrections :

Il existe plusieurs façons de résoudre cette course aux données :

  • Créez une nouvelle variable dans le boucle :
for _, v := range data {
    v := v        // short variable declaration of new variable `v`.
    go v.print()
}
Copier après la connexion
  • Utiliser une tranche de pointeurs :
data := []*field{{"one"}, {"two"}, {"three"}} // note '*'
for _, v := range data {
    go v.print()
}
Copier après la connexion
  • Utiliser l'adresse de la tranche element :
data := []field{{"one"}, {"two"}, {"three"}} // note '*'
for i := range data {
    v := &data[i]
    go v.print()
}
Copier après la connexion
  • Passez la variable de plage en argument à une fonction anonyme :
for _, v := range data {
  go func(v field) {
    v.print() // take address of argument v, not range variable v.
  }(v)
}
Copier après la connexion

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