En Go, il est possible d'envoyer des valeurs de n'importe quel type par des canaux : int, struct, pointeurs, interfaces, etc.
Code et exemple :
type Data struct { N int } c := make(chan Data) d := Data{N: 1} c <- d // la structure est entièrement copiée p := &Data{N: 3} c2 := make(chan *Data) c2 <- p // un pointeur vers le même objet est envoyé par le canal
Si une structure contenant un champ pointeur est transmise par le canal — y aura-t-il une condition de course lors de la modification de ce champ aux deux extrémités du canal ?
Réponse :
Exemple :
type Box struct { Ptr *int } x := 10 chanBox := make(chan Box) chanBox <- Box{Ptr: &x} // l'expéditeur et le destinataire ont tous deux accès à x !
Histoire
Dans une file d'attente distribuée, il y avait des arrêts "aléatoires" fréquents et des valeurs mystérieuses dans la structure de la tâche. Il s'est avéré que des pointeurs vers des structures communes étaient transférés par le canal, qui étaient modifiés en parallèle dans plusieurs goroutines. Nous avons décidé de passer à la transmission de copies de données.
Histoire
Le traitement asynchrone des messages fonctionnait avec des structures contenant des tranches-pointeurs vers un tableau commun. Lors de la transmission parallèle par le canal, des parties de la même mémoire étaient modifiées depuis différents endroits, entraînant des bogues secrets et une corruption des données.
Histoire
Dans le service de notifications push, des références à des objets étaient transmises par le canal, qui étaient ensuite traitées par des goroutines. Lors de la terminaison simultanée et de la fermeture du canal, certaines structures étaient encore modifiées, provoquant une panique ou une condition de course. Le passage à la copie de la structure avant l'envoi a aidé.