Histoire de la question :
Les canaux (chan) sont l'outil clé pour l'échange de données entre goroutines et la synchronisation de processus concurrents, ce qui distingue clairement Go des autres langages. Ils sont conçus pour organiser un transfert de données sécurisé pour les threads.
Problème :
Sans une compréhension correcte du fonctionnement des canaux, les développeurs se heurtent souvent à des blocages, des blocages inattendus, des erreurs peu évidentes lors de la fermeture du canal et à la perte de données (conditions de compétition).
Solution :
Il est essentiel de comprendre comment déclarer, utiliser et fermer les canaux. Il faut décider quand utiliser des canaux tamponnés/non tamponnés et surveiller qui et quand doit fermer le canal pour éviter "tout est bloqué".
Exemple de code :
func producer(ch chan<- int) { // uniquement envoi for i := 0; i < 5; i++ { ch <- i } close(ch) } func consumer(ch <-chan int) { // uniquement lecture for v := range ch { fmt.Println(v) } } func main() { ch := make(chan int) go producer(ch) consumer(ch) }
Caractéristiques clés :
Que se passe-t-il lorsque vous essayez d'écrire dans un canal fermé ?
Une panique surviendra. Une erreur assez fréquente est de fermer le canal du côté du lecteur ou de permettre l'écriture dans le canal après sa fermeture.
Peut-on savoir en toute sécurité si un canal est fermé ?
Non, il n'y a pas de vérification directe. Il faut uniquement concevoir correctement le contrôle de la durée de vie du canal, ou utiliser le second paramètre lors de la lecture (v, ok := <-ch), qui deviendra faux lorsqu'on fermera le canal.
Un canal est-il intrinsèquement thread-safe ?
Un canal est thread-safe pour le transfert de données entre goroutines. Mais si plusieurs goroutines écrivent dans un canal sans coordination, cela peut entraîner des problèmes (comme une fermeture prématurée).
Un projet avec plusieurs producteurs et un consommateur : chaque producteur fermait le canal, ce qui entraînait une panique à l'exécution lors d'une double fermeture, les données étaient perdues.
Avantages :
Inconvénients :
Utilisation d'un seul thread pour fermer le canal, et les producteurs signalaient la fin de leur travail via un WaitGroup distinct. Le canal servait uniquement à transmettre les résultats.
Avantages :
Inconvénients :