Programmation concurrente avec des goroutines

14611 단어 gofrench
누벨 안네, 누보 챌린지 ! Ca fait pas mal de temps de je lorgne sur le Go (ou Golang) et ça y est, il est venu le temps de s'y mettre !
Avant cela, j'ai (un peu) mis à jour mon site et rajouter un lien pour ma page LinkedIn : n'hésitez pas à me suivre ou m'ajouter afin de recevoir les prochaines mises à jour 😊.

Le Go (ou Golang) est un langage développé depuis quelques années désormais (plus de 10 ans) par une équipe de Google, et pas des débutants ! Notamment Brian Kernighan , éminent informaticien en C et autre. Ils ont alors developpé ce langage pour simplifier l'utilisation du multithreading, 원칙적으로 au coeur du Go.

Je vais vous présenter içi les goroutines , 기본 원칙은 다중 스레딩 및 다중 스레딩 작업을 위한 것입니다.

정의



Programmation concurente: Composition de plusieurs activités autonomes.

프로그래밍 동시 지원 유형:
  • CSP(통신 순차 프로세스 - 통신 프로세스 시퀀스). Les variables sont passées entre des activités indépendamment mais les variables sont la plus part du temps confinées à une seule de ces activités.

  • 공유 메모리 멀티스레딩(multithreading à memoire partagee)

  • 고루틴 : activité exécutée en concurrence



    Maintenant que nous avons vu le principe de base, place aux exemples !

    바스크어



    On va faire un simplehello world ! mais en utilisant unegoroutine . On va écrire une fonction say qui prend une string en argument et que l'on appelera en tant que goroutine (avec le mot-clé go ) et qui nous affichera "hello". Voyons ce que ça donne :

    package main
    import "fmt"
    
    
    func say(s string) {
        fmt.Println(s)
    }
    
    func main() {
        go say("hello")
        fmt.Println("world !")
    }
    


    출격 :

    world !
    


    쿠이?!? Mais il manque un bout !!! 😱😱😱
    설명: la boucle principalemain n'attend pas la fin de l'execution de lagoroutine . Pour le moment, on va résoudre ça avec un simplesleep . 다음 코드를 수정할 때:

    package main
    
    import (
        "fmt"
        "time"
    )
    
    func say(s string) {
        fmt.Println(s)
    }
    
    func main() {
        go say("hello")
        fmt.Println("world !")
        time.Sleep(500 * time.Millisecond)
    }
    


    명백한 출격:

    world !
    hello
    


    아!!!!! 짜잔! On obtient bien ce que l'on souhaite en sortie mais c'est loin d'être 최적...

    On peut faire beaucoup mieux!! 플레이스 알라 스위트 😉

    참석자 plusieurs goroutines



    Lorsque l'on a besoin d'attendre que une ou plusieursgoroutine finissent, on use le packetsync et la fonctionsync.WaitGroup . Elle est utilisé pour bloquer le main (ou toute autre fonction appelante) jusqu'à ce que toutes les goroutine aient terminé leur travail. Un example parlant (adapté de l'article How to wait for all goroutines to finish in Golang ) :

    package main
    
    import (
        "fmt"
        "sync"
        "time"
    )
    
    func worker(wg *sync.WaitGroup, id int) {
        defer wg.Done() //décrémentation (lorsque la goroutine a terminé)
    
        fmt.Printf("Worker %v: Début\n", id)
        time.Sleep(time.Second)
        fmt.Printf("Worker %v: Terminé\n", id)
    }
    
    func main() {
        var wg sync.WaitGroup // déclaration
    
        for i := 0; i < 5; i++ {
            fmt.Println("Main: Lancement du Worker", i)
            wg.Add(1) // incrémentation d'une unité
            go worker(&wg, i) // passage par adresse
        }
    
        fmt.Println("Main: En attente des Workers")
        wg.Wait()
        fmt.Println("Main: Terminé")
    }
    


    Ce qui donne :

    Main: Lancement du Worker 0
    Main: Lancement du Worker 1
    Main: Lancement du Worker 2
    Main: Lancement du Worker 3
    Main: Lancement du Worker 4
    Worker 0: Début
    Worker 4: Début
    Worker 2: Début
    Main: En attente des Workers
    Worker 1: Début
    Worker 3: Début
    Worker 1: Terminé
    Worker 0: Terminé
    Worker 4: Terminé
    Worker 2: Terminé
    Worker 3: Terminé
    Main: Terminé
    


    N'est-ce pas formidable ?

    L'utilisation de WaitGroup est assez simple :
  • 디클레이션 단스 르main
  • 증분 avec .Add(1) avant l'appel de la goroutine
  • appel de la goroutine avec passage par adresse du WaitGroup
  • decrémentation du WaitGroup au sein de la goroutine avec .Done()
  • en fin de bloc, on 참석 라 핀 데 goroutine avec .Wait()

  • Notez l'utilisation de defer pour la décrémentation dès le début de la goroutine . Ce mot-clé permet de s'assurer que la fonction qui le suit sera bien appelée à la fin du bloc. On le retrouve pour la course des fichiers: on s'assure ainsi que ce dernier sera bien fermé à la fin du traitement.

    고루틴 익명



    Lorsque la goroutine ne fait quelques lignes (pas trop, sinon le code devient vite illisible...), il est possible d'utiliser une fonction anonyme. Voyons avec l'exemple précédent ce que cela change :

    package main
    
    import (
        "fmt"
        "sync"
        "time"
    )
    
    func main() {
        var wg sync.WaitGroup // déclaration
    
        for i := 0; i < 5; i++ {
            fmt.Println("Main: Lancement du Worker", i)
            wg.Add(1) // incrémentation d'une unité
    
            go func(id int) { // fonction anonyme
                defer wg.Done() //décrémentation (lorsque la goroutine a terminé)
    
                fmt.Printf("Worker %v: Début\n", id)
                time.Sleep(time.Second)
                fmt.Printf("Worker %v: Terminé\n", id)
            }(i)
        }
    
        fmt.Println("Main: En attente des Workers")
        wg.Wait()
        fmt.Println("Main: Terminé")
    }
    


    세 운 프 플러스 컨시스 😊

    결론



    Voilà, c'est terminé pour cette petite presentation ! J'ai utilisé également les livres suivant dans mon apprentissage :
  • The Go Programming Language
  • Learning Go: An Idiomatic Approach to Real-World Go Programming

  • 비앙또!

    좋은 웹페이지 즐겨찾기