Tutoriel sur les canaux Go

Dans ce tutoriel, nous allons examiner comment vous pouvez utiliser les canaux dans vos applications basées sur Go.Les canaux

sont des canaux qui relient goroutines dans vos applications Go basedapplications qui permettent la communication et par la suite le passage de valeurs vers et à partir de variables.

Ils sont incroyablement pratiques et peuvent vous aider à créer des applications extrêmement performantes et hautement concurrentes en Go avec un minimum de tracas par rapport aux autres langages de programmation. Ce n’était en aucun cas un hasard, lors de la conception de la langue, les développeurs principaux ont décidé qu’ils voulaient que la concurrence au sein de leur langue soit un citoyen de première classe et qu’il soit aussi simple de travailler avec aspossible, sans aller trop loin et ne laissant pas aux développeurs la liberté dans laquelle ils devaient travailler.

La capacité de concevoir des systèmes concurrents si facilement est quelque chose qui m’a attiré vers le langage en premier lieu, et je dois dire que cela a été une lumière absolue jusqu’à présent.

Remarque – Je vous recommande de jeter un coup d’œil à mon autre tutoriel sur les goroutines si vous souhaitez en savoir plus sur les goroutines.

Objectifs

À la fin de ce tutoriel, vous allez:

  • Avoir une compréhension solide de la théorie derrière les canaux
  • Être capable de créer des applications Go simultanées simples qui utilisent les canaux

Prérequis

Pour terminer ce tutoriel, vous devrez avoir satisfait aux exigences suivantes:

  • Vous devrez installer Go sur votre machine.

Tutoriel vidéo

Si vous le souhaitez, ce tutoriel est disponible en format vidéo.

La Théorie

L’idée de canaux n’est pas nouvelle, car comme beaucoup de fonctionnalités concurrentielles de Go, ces concepts ont été avancés à partir de processus séquentiels communicants de Hoare’s (1978), CSP pour faire court, et même à partir des commandes gardées de Dijkstra (1975).

Les développeurs de Go, cependant, se sont donné pour mission de présenter ces concepts de la manière la plus simple possible pour permettre aux programmeurs de créer des applications plus belles, plus correctes et hautement concurrentes.

Un exemple simple

Commençons par voir comment nous pouvons construire un exemple très simple de comment cela fonctionne dans Go. Nous allons d’abord créer une fonction qui disparaît et calcule une valeur aléatoire anarbitraire et la transmet à une variable de canal appeléevalues:

principal.allez

Voyons ce qui s’est passé ici. Dans notre fonction main(), que nous avons appelée values := make(chan int), cet appel a effectivement créé notre nouveau canal afin que nous puissions ensuite l’utiliser dans notre goroutine CalculateValue.

Remarque – Nous avons utilisé make lors de l’instanciation de notre canal values car, likemaps et tranches, les canaux doivent être créés avant utilisation.

Après avoir créé le canal, nous avons ensuite appelé defer close(values) qui a annulé la fermeture de notre canal jusqu’à la fin de l’exécution de notre fonction main(). Ceci est généralement considéré comme la meilleure pratique pour nous assurer que nous rangeons après nous-mêmes.

Après notre appel au defer, nous lançons notre unique goroutine: CalculateValue(values) en passant dans notre nouveau canal values en tant que paramètre. Dans notre fonction CalculateValue, nous calculons une seule valeur aléatoire comprise entre 1 et 10, l’imprimons puis envoyons cette valeur à notre canal values en appelant values <- value.

En retournant dans notre fonction main(), nous appelons ensuite value := <-values qui reçoit une valeur de notre canal values.

Remarque – Notez que lorsque nous exécutons ce programme, il ne se termine pas immédiatement. En effet, l’acte d’envoyer et de recevoir d’un canal est bloqué. Notre fonction main() bloque jusqu’à ce qu’elle reçoive une valeur de ourchannel.

Lors de l’exécution de ce code, vous devriez voir la sortie ressembler à ceci:

$ go run main.goGo Channel TutorialCalculated Random Value: {} 77

Résumé:

myChannel := make(chan int) – crée myChannel qui est un canal de typeint

channel <- value – envoie une valeur à un canal

value := <- channel – reçoit une valeur d’un canal

Ainsi, l’instanciation et l’utilisation des canaux dans vos programmes Go semblent assez rapides jusqu’à présent, mais qu’en est-il dans des scénarios plus complexes?

Canaux non tamponnés

L’utilisation d’un channel traditionnel dans vos goroutines peut parfois entraîner des problèmes de comportement auxquels vous ne vous attendez peut-être pas tout à fait. Avec les canaux traditionnels unbuffered, chaque fois qu’un goroutine envoie une valeur à ce canal, ce goroutine bloquera ensuite jusqu’à ce que la valeur soit reçue du canal.

Voyons cela dans un exemple réel. Si nous regardons le code ci-dessous, c’est trèssimilaire au code que nous avions précédemment. Cependant, nous avons étendu notre fonction CalculateValue() pour effectuer une fmt.Println après avoir envoyé sa valeur calculée au canal.

Dans notre fonction main(), nous avons ajouté un deuxième appel à go CalculateValue(valueChannel), nous devons donc nous attendre à ce que 2 valeurs soient envoyées à ce canal très rapidement.

principal.go

Cependant, lorsque vous exécutez cela, vous devriez voir que seule l’instruction finalprint de nos premières goroutines est réellement exécutée:

go run main.goGo Channel TutorialCalculated Random Value: {} 1Calculated Random Value: {} 71Only Executes after another goroutine performs a receive on the channel

La raison en est que notre appel à c <- value s’est bloqué dans notre secondgoroutine et que par la suite la fonction main() conclut son exécution avant que notre deuxième goroutine ait une chance de terminer sa propre exécution.

Canaux tamponnés

La façon de contourner ce comportement de blocage consiste à utiliser quelque chose appelé canal abuffered. Ces canaux mis en mémoire tampon sont essentiellement des files d’attente d’une taille donnéequi peuvent être utilisées pour la communication inter-goroutine. Afin de créer un canal abuffered par opposition à un canal unbuffered, nous fournissons un capacityargument à notre commande make:

bufferedChannel := make(chan int, 3)

En changeant cela en canal tamponné, notre opération d’envoi, c <- value ne bloque que dans nos goroutines si le canal est plein.

Modifions notre programme existant pour utiliser un canal tamponné et regardons la sortie. Notez que j’ai ajouté un appel à time.Sleep() au bas de notre fonction main() afin de bloquer paresseusement notre fonction main() suffisamment pour permettre à nos goroutines de terminer l’exécution.

principal.go

Maintenant, lorsque nous exécutons cela, nous devrions voir que notre deuxième goroutine continue effectivement son exécution indépendamment du fait qu’une deuxième réception n’a pas été appelée dans notre fonction main(). Grâce au time.Sleep(), nous pouvons clairement voir la différence entre les canaux non tamponnés et leur nature bloquante et nos canaux tamponnés et leur nature non bloquante (lorsqu’ils ne sont pas pleins).

Go Channel TutorialCalculated Random Value: {} 1Calculated Random Value: {} 77This executes regardless as the send is now non-blockingThis executes regardless as the send is now non-blocking

Conclusion

Ainsi, dans ce tutoriel assez long, nous avons réussi à en apprendre davantage sur les différents types de canaux distincts de Go. Nous avons découvert les différences entre les canaux tamponnés et non tamponnés et comment nous pourrions les utiliser à notre avantage dans nos programmes go concurrents.

Si vous avez apprécié ce tutoriel, n’hésitez pas à me le faire savoir dans la section commentaires ci-dessous. Si vous avez des suggestions sur ce que je pourrais faire de mieux, alors j’aimerais les entendre dans la section des commentaires ci-dessous!

Pour en savoir plus

Si vous avez apprécié cet article et que vous souhaitez en savoir plus sur le travail avec Concurrencyin Go, je vous recommande de consulter nos autres articles sur la concurrence:

  • Tutoriel Go Mutex
  • Tutoriel Go Goroutines
  • Synchronisation Go.Tutoriel du groupe d’attente

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.

Previous post Système de bibliothèque du comté de Brunswick
Next post Devriez-Vous Peindre ou Tacher des armoires? Avantages et inconvénients de Chaque