Comportement de Goroutine : résoudre le mystère
Nous tombons sur un comportement déroutant dans le code Go fourni :
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) }
La question se pose : pourquoi ce code imprime-t-il systématiquement "trois" trois fois, au lieu d'afficher "un", "deux" et "trois" dans n'importe quel ordre ?
Comprendre le problème
Le nœud du problème réside dans une subtile condition de concurrence provoquée par l'utilisation de la variable de plage v dans la fonction goroutine.
Lorsque nous écrivons v.print(), nous passons effectivement un pointeur vers la variable v, qui est une référence à l'élément actuel dans la boucle de données de plage. Cependant, la boucle continue d'itérer, modifiant la valeur de v.
Lorsque la goroutine s'exécute, elle a la valeur finale de v, qui est "trois". Cela produit le résultat inattendu de trois « trois ».
Résoudre le problème : approches multiples
Il existe plusieurs façons de résoudre ce problème :
1. Utilisation d'une déclaration de variable courte :
Créez une nouvelle variable v limitée à chaque itération de la boucle :
for _, v := range data { v := v // Short variable declaration to create a new `v`. go v.print() }
2. Utilisation d'une tranche de pointeurs :
Changez le type de données en une tranche de pointeurs et transmettez les pointeurs individuels à la fonction goroutine :
data := []*field{{"one"}, {"two"}, {"three"}} // Note the '*' for _, v := range data { go v.print() }
3. Utilisation de l'adresse de l'élément Slice :
Prenez l'adresse de chaque élément slice et passez le pointeur vers la fonction goroutine :
data := []*field{{"one"}, {"two"}, {"three"}} // Note the '*' for i := range data { v := &data[i] go v.print() }
Conclusion
N'oubliez pas que prendre des adresses de variables de plage peut entraîner un comportement inattendu dans les goroutines si la boucle modifie la valeur des variables. En utilisant les techniques décrites ci-dessus, nous pouvons garantir que chaque goroutine reçoit une valeur unique et éviter les problèmes de course aux données.
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!