En Go, un canal est un moyen de transmission de données entre des goroutines avec synchronisation. On distingue :
Utiliser des canaux non tamponnés est pratique là où la synchronisation est critique, et il est nécessaire de garantir que l'expéditeur et le destinataire se rencontrent au même endroit dans le code. Les canaux tamponnés conviennent pour la transmission de données "avec réserve" — pour organiser des files d'attente, des travailleurs, des tâches asynchrones.
func main() { ch := make(chan int) // canal non tamponné go func() { ch <- 42 // se bloque tant qu'il n'y a pas de récepteur }() fmt.Println(<-ch) bufch := make(chan int, 2) // canal tamponné de 2 éléments bufch <- 1 // ne se bloque pas bufch <- 2 // ne se bloque pas // le prochain envoi se bloquera s'il n'y a pas de lecture }
Un canal tamponné peut-il servir de remplacement à une file d'attente entre des dizaines de producteurs et de consommateurs sans synchronisation supplémentaire ?
On répond souvent — « oui ». En réalité, seulement si l'ordre n'est pas important et que les messages ne sont pas perdus. Avec plusieurs lecteurs/écrivains, des situations de concurrence et de perte de données peuvent se produire, donc un contrôle de synchronisation est toujours nécessaire (piscine de travailleurs, mutex, contextes pour fermer les canaux).
Histoire
Dans le traitement des logs, les programmeurs utilisaient un canal tamponné de longueur 1000 pour transmettre des événements entre le parseur et l'agrégateur. Lorsqu'ils ont arrêté le service, ils ont oublié de fermer le canal, et une partie des événements a été "perdue" — les travailleurs se sont terminés avant que tout le tampon ne soit traité. Cela a été corrigé par la fermeture explicite des canaux et un verrouillage jusqu'à ce que tout soit complètement vidé.
Histoire
En essayant de remplacer une file d'attente utilisant un mutex par un canal tamponné dans un service distribué, ils n'ont pas pris en compte les situations d'expéditeurs "bloqués" : avec un tampon plein, le blocage de l'envoi a finalement ralenti tout le système, provoquant des délais d'attente, et l'interface a commencé à "laguer". Après analyse, une partie de la synchronisation a été réintroduite via des variables de condition.
Histoire
Dans un module de télémétrie, un canal non tamponné était utilisé pour le journal des erreurs entre le module et le consommateur. En raison d'un retard aléatoire de traitement, l'écrivain était bloqué, et en une minute, une file d'attente de centaines de milliers de données s'est accumulée dans les goroutines — entraînant un "out of goroutines". Cela a été corrigé en remplaçant le canal non tamponné par un canal tamponné et un travailleur asynchrone pour nettoyer la file d'attente.