Découvrez comment les goroutines et les canaux permettent une simultanéité efficace dans vos programmes Go.
La simultanéité est un aspect crucial du développement de logiciels modernes car elle permet aux programmes de gérer efficacement plusieurs tâches simultanément. Vous pouvez écrire des programmes qui exécutent diverses opérations conduisant à une amélioration des performances, de la réactivité et de l'utilisation des ressources.
La simultanéité est l'une des caractéristiques responsables de l'adoption rapide de Go. La prise en charge intégrée de Go pour la programmation simultanée est considérée comme simple tout en aidant à éviter les pièges courants tels que les conditions de concurrence et les blocages.
Concurrence en Go
Go fournit une prise en charge robuste de la concurrence via divers mécanismes, tous disponibles dans sa bibliothèque et sa chaîne d'outils standard. Allez programmes atteindre la concurrence par le biais de goroutines et de canaux.
Les goroutines sont légères, exécutant indépendamment des fonctions qui s'exécutent simultanément avec d'autres goroutines dans le même espace d'adressage. Les goroutines permettent à plusieurs tâches de progresser simultanément sans gestion explicite des threads. Les goroutines sont plus légères que les threads du système d'exploitation et Go peut exécuter efficacement des milliers, voire des millions de goroutines simultanément.
Les canaux sont le mécanisme de communication pour la coordination et le partage de données entre les goroutines. Un canal est un conduit typé qui permet aux goroutines d'envoyer et de recevoir des valeurs. Les canaux fournissent une synchronisation pour assurer un partage de données sécurisé entre les goroutines tout en évitant les conditions de concurrence et d'autres problèmes de simultanéité courants.
En combinant les goroutines et les canaux, Go fournit un modèle de concurrence puissant et simple qui simplifie le développement de programmes simultanés tout en maintenant la sécurité et l'efficacité. Ces mécanismes vous permettent d'utiliser facilement processeurs multicœurs et créez des applications hautement évolutives et réactives.
Comment utiliser Goroutines pour l'exécution simultanée de code
Le runtime Go gère les goroutines. Les goroutines ont leur pile, ce qui leur permet d'avoir une empreinte légère avec une taille de pile initiale de quelques kilo-octets.
Les goroutines sont multiplexées sur plusieurs threads du système d'exploitation par le runtime Go. Le planificateur d'exécution Go les planifie sur les threads disponibles en distribuant efficacement la charge de travail, permettant l'exécution simultanée de plusieurs goroutines sur moins de threads du système d'exploitation.
La création de goroutines est simple. Vous utiliserez le aller mot-clé suivi d'un appel de fonction pour déclarer des goroutines.
fonctionprincipal() {
aller fonction1() // Crée et exécute une goroutine pour la fonction1
aller fonction2() // Crée et exécute une goroutine pour la fonction2// ...
}fonctionfonction1() {
// Code pour la fonction1
}
fonctionfonction2() {
// Code pour la fonction2
}
Lorsque le programme invoque fonction1() et fonction2() avec le aller, le runtime Go exécute les fonctions simultanément en tant que goroutines.
Voici un exemple d'utilisation d'une goroutine qui imprime du texte sur la console :
emballer principal
importer (
"fmt"
"temps"
)fonctionprintText() {
pour je := 1; je <= 5; je++ {
fmt. Imprimerln("Impression de texte", je)
temps. Dormir(1 * temps. Deuxième)
}
}fonctionprincipal() {
aller printText() // Démarre une goroutine pour exécuter la fonction printText simultanément// Effectuer d'autres tâches dans la goroutine principale
pour je := 1; je <= 5; je++ {
fmt. Imprimerln("Effectuer d'autres tâches", je)
temps. Dormir(500 * temps. milliseconde)
}
// Attendre que la goroutine se termine
temps. Dormir(6 * temps. Deuxième)
}
Le printText fonction imprime à plusieurs reprises du texte sur la console avec un pour boucle qui s'exécute cinq fois après un délai d'une seconde entre chaque instruction avec le forfait horaire.
Le principal la fonction démarre une goroutine en appelant aller imprimerTexte, qui lance le printText fonctionner comme une goroutine concurrente distincte qui permet à la fonction de s'exécuter simultanément avec le reste du code dans le principal fonction.
Enfin, pour s'assurer que le programme ne se termine pas avant le printText goroutine se termine, le temps. Dormir La fonction met en pause la goroutine principale pendant six secondes. Dans des scénarios réels, vous utiliseriez des mécanismes de synchronisation tels que des canaux ou des groupes d'attente pour coordonner l'exécution des goroutines.
Utilisation de canaux pour la communication et la synchronisation
Les goroutines ont un support intégré pour la communication et la synchronisation via les canaux, ce qui rend l'écriture simultanée code plus facile que les threads traditionnels, qui nécessitent souvent des mécanismes de synchronisation manuelle comme les verrous et sémaphores.
Vous pouvez considérer les canaux comme des pipelines pour le flux de données entre les goroutines. Une goroutine peut envoyer une valeur dans le canal, et une autre goroutine peut recevoir cette valeur du canal. Ce mécanisme garantit que l'échange de données est sûr et synchronisé.
Vous utiliserez le opérateur d'envoyer et de recevoir des données via des canaux.
Voici un exemple démontrant l'utilisation de base des canaux de communication entre deux goroutines :
fonctionprincipal() {
// Crée un canal sans tampon de type chaîne
ch := faire(chansonchaîne)// Goroutine 1: Envoie un message dans le canal
allerfonction() {
ch "Bonjour, Canal !"
}()
// Goroutine 2: Reçoit le message du canal
message := fmt. Imprimerln (msg) // Sortie: Bonjour, Channel !
}
Le canal dans le principal la fonction est un canal non tamponné nommé ch créé avec le faire() fonction. La première goroutine envoie le message "Hello, Channel!" dans le canal à l'aide du opérateur, et la deuxième goroutine reçoit le message du canal en utilisant le même opérateur. Finalement, le principal La fonction imprime le message reçu sur la console.
Vous pouvez définir des canaux typés. Vous spécifierez le type de chaîne lors de la création. Voici un exemple illustrant l'utilisation de différents types de canaux :
fonctionprincipal() {
// Canal sans tampon
ch1 := faire(chansonentier)// Canal tamponné d'une capacité de 3
ch2 := faire(chansonchaîne, 3)// Envoi et réception des valeurs des canaux
ch1 42// Envoie une valeur dans ch1
valeur1 := // Reçoit une valeur de ch1
ch2 "Bonjour"// Envoie une valeur dans ch2
valeur2 := // Reçoit une valeur de ch2
}
Le principal La fonction crée deux canaux: ch1 est un canal entier sans tampon, tandis que ch2 est un canal de chaîne tamponné d'une capacité de 3. Vous pouvez envoyer et recevoir des valeurs vers et depuis ces canaux à l'aide du opérateur (les valeurs doivent être du type spécifié).
Vous pouvez utiliser des canaux comme mécanismes de synchronisation pour coordonner l'exécution d'une goroutine en tirant parti de la nature bloquante des opérations de canal.
fonctionprincipal() {
ch := faire(chansonbourdonner)allerfonction() {
fmt. Imprimerln("Goroutine 1")
ch vrai// Signal d'achèvement
}()allerfonction() {
// Attendre le signal d'achèvement de Goroutine 1
fmt. Imprimerln("Goroutine 2")
}()
// Attendre le signal d'achèvement de Goroutine 2
fmt. Imprimerln("Groutine principale")
}
Le ch canal est booléen. Deux goroutines s'exécutent simultanément dans le principal fonction. Goroutine 1 signale son achèvement en envoyant un vrai valeur dans le canal ch. Goroutine 2 attend le signal d'achèvement en recevant une valeur du canal. Enfin, la goroutine principale attend le signal d'achèvement de la goroutine deux.
Vous pouvez créer des applications Web dans Go With Gin
Vous pouvez créer des applications Web hautes performances dans Go avec Gin tout en tirant parti des fonctionnalités de simultanéité de Go.
Vous pouvez utiliser Gin pour gérer efficacement le routage HTTP et le middleware. Tirez parti de la prise en charge intégrée de la simultanéité de Go en utilisant des goroutines et des canaux pour des tâches telles que les requêtes de base de données, les appels d'API ou d'autres opérations de blocage.