首页 > 后端开发 > Golang > 正文

如何在 Go 中使用 Goroutines 进行并发处理

Linda Hamilton
发布: 2024-10-12 06:31:02
原创
514 人浏览过

How to Use Goroutines for Concurrent Processing in Go

La concurrence est l'une des fonctionnalités déterminantes de Go, ce qui en fait un langage fantastique pour créer des applications évolutives et hautes performances. Dans cet article, nous explorerons les Goroutines, qui vous permettent d'exécuter des fonctions simultanément dans Go, donnant ainsi à vos applications un sérieux gain d'efficacité. Que vous travailliez sur un serveur Web, un processeur de données ou tout autre type d'application, Goroutines peut vous aider à faire plus avec moins.

Voici ce que nous allons aborder :

  • Qu'est-ce que les Goroutines et comment elles fonctionnent.
  • Comment créer et utiliser des Goroutines.
  • Synchronisation des Goroutines avec les WaitGroups et les canaux.
  • Pièges courants et meilleures pratiques pour travailler avec Goroutines.

Commençons ! ?


Que sont les Goroutines ? ?

Les Goroutines sont des threads légers gérés par le runtime Go, vous permettant d'exécuter des fonctions simultanément. Contrairement aux threads au niveau du système d’exploitation, les Goroutines sont beaucoup moins chères et plus efficaces. Vous pouvez générer des milliers de Goroutines sans surcharger votre système, ce qui les rend idéales pour les tâches simultanées.

Principales caractéristiques :

  • Efficace : les Goroutines utilisent un minimum de mémoire et démarrent rapidement.
  • Exécution simultanée : ils peuvent exécuter plusieurs fonctions en même temps, vous aidant ainsi à gérer des tâches en parallèle.
  • Facile à utiliser : vous n'avez pas besoin de gérer une logique de thread complexe.

Créer et utiliser des Goroutines

Créer une Goroutine est incroyablement simple : il suffit d'utiliser le mot-clé go avant un appel de fonction. Regardons un exemple rapide.

Exemple de base :

package main

import (
    "fmt"
    "time"
)

func printMessage(message string) {
    for i := 0; i < 5; i++ {
        fmt.Println(message)
        time.Sleep(500 * time.Millisecond)
    }
}

func main() {
    go printMessage("Hello from Goroutine!")  // This runs concurrently
    printMessage("Hello from main!")
}
登录后复制

Dans cet exemple, printMessage est appelé comme Goroutine avec go printMessage("Hello from Goroutine!"), ce qui signifie qu'il s'exécutera en même temps que la fonction principale.


Synchronisation des Goroutines avec les WaitGroups

Étant donné que les Goroutines s'exécutent simultanément, elles peuvent terminer dans n'importe quel ordre. Pour vous assurer que toutes les Goroutines sont terminées avant de continuer, vous pouvez utiliser un WaitGroup du package de synchronisation de Go.

Exemple avec WaitGroup :

package main

import (
    "fmt"
    "sync"
    "time"
)

func printMessage(message string, wg *sync.WaitGroup) {
    defer wg.Done() // Notify WaitGroup that the Goroutine is done
    for i := 0; i < 5; i++ {
        fmt.Println(message)
        time.Sleep(500 * time.Millisecond)
    }
}

func main() {
    var wg sync.WaitGroup

    wg.Add(1)
    go printMessage("Hello from Goroutine!", &wg)

    wg.Add(1)
    go printMessage("Hello again!", &wg)

    wg.Wait()  // Wait for all Goroutines to finish
    fmt.Println("All Goroutines are done!")
}
登录后复制

Ici, nous ajoutons wg.Add(1) pour chaque Goroutine et appelons wg.Done() lorsque la Goroutine est terminée. Enfin, wg.Wait() met la fonction principale en pause jusqu'à ce que toutes les Goroutines soient terminées.


Communiquer entre Goroutines avec des canaux

Les

Canaux sont le moyen intégré de Go permettant aux Goroutines de communiquer. Ils vous permettent de transmettre des données en toute sécurité entre Goroutines, garantissant ainsi qu'aucune course aux données ne se produise.

Exemple de canal de base :

package main

import (
    "fmt"
)

func sendData(channel chan string) {
    channel <- "Hello from the channel!"
}

func main() {
    messageChannel := make(chan string)

    go sendData(messageChannel)

    message := <-messageChannel  // Receive data from the channel
    fmt.Println(message)
}
登录后复制

Dans cet exemple, sendData envoie un message à messageChannel et la fonction principale le reçoit. Les canaux aident à synchroniser les Goroutines en bloquant jusqu'à ce que l'expéditeur et le destinataire soient prêts.

Utilisation de canaux tamponnés

Vous pouvez également créer des canaux tamponnés qui permettent de stocker un nombre défini de valeurs dans le canal avant qu'il ne se bloque. Ceci est utile lorsque l'on souhaite gérer les flux de données sans nécessairement synchroniser chaque Goroutine.

func main() {
    messageChannel := make(chan string, 2)  // Buffered channel with capacity of 2

    messageChannel <- "Message 1"
    messageChannel <- "Message 2"
    // messageChannel <- "Message 3" // This would block as the buffer is full

    fmt.Println(<-messageChannel)
    fmt.Println(<-messageChannel)
}
登录后复制

Les canaux tamponnés ajoutent un peu plus de flexibilité, mais il est important de gérer soigneusement la taille des tampons pour éviter les blocages.


Pièges courants et meilleures pratiques

  1. Éviter de bloquer les Goroutines : Si une Goroutine se bloque et qu'il n'y a aucun moyen de la libérer, vous vous retrouverez dans une impasse. Utilisez des canaux ou l'annulation de contexte pour éviter cela.

  2. Utiliser select avec les canaux : lorsque vous travaillez avec plusieurs canaux, l'instruction select vous permet de gérer le canal qui est prêt en premier, évitant ainsi un blocage potentiel.

   select {
   case msg := <-channel1:
       fmt.Println("Received from channel1:", msg)
   case msg := <-channel2:
       fmt.Println("Received from channel2:", msg)
   default:
       fmt.Println("No data received")
   }
登录后复制
  1. Fermer correctement les chaînes : La fermeture des chaînes signale qu'aucune donnée ne sera envoyée, ce qui est utile pour indiquer quand un Goroutine a fini d'envoyer des données.
   close(messageChannel)
登录后复制
  1. Surveiller l'utilisation de la mémoire : Étant donné que les Goroutines sont si légères, il est facile d'en générer trop. Surveillez l'utilisation de la mémoire de votre application pour éviter de surcharger le système.

  2. Utiliser le contexte pour l'annulation : lorsque vous devez annuler les Goroutines, utilisez le package contextuel de Go pour propager les signaux d'annulation.

   ctx, cancel := context.WithCancel(context.Background())
   defer cancel()

   go func(ctx context.Context) {
       for {
           select {
           case <-ctx.Done():
               return
           default:
               // Continue processing
           }
       }
   }(ctx)
登录后复制

Pensées finales

Les Goroutines sont une fonctionnalité puissante de Go, rendant la programmation simultanée accessible et efficace. En tirant parti des Goroutines, des WaitGroups et des canaux, vous pouvez créer des applications qui gèrent les tâches simultanément, évoluent efficacement et exploitent pleinement les processeurs multicœurs modernes.

尝试一下:在您自己的项目中尝试 Goroutine!一旦掌握了它们的窍门,您就会发现它们为 Go 应用程序打开了一个充满可能性的全新世界。快乐编码! ?


您最喜欢的 Goroutine 用例是什么?请在评论中告诉我,或者分享您有效使用 Goroutine 的任何其他技巧!

以上是如何在 Go 中使用 Goroutines 进行并发处理的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:dev.to
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责声明 Sitemap
PHP中文网:公益在线PHP培训,帮助PHP学习者快速成长!