Maison  >  Article  >  développement back-end  >  Écrivez le canal en synchronisation.WaitGroup goroutine

Écrivez le canal en synchronisation.WaitGroup goroutine

PHPz
PHPzavant
2024-02-09 17:00:10690parcourir

在sync.WaitGroup goroutine中写入chan

L'éditeur PHP Youzi présentera une méthode d'écriture de chan en goroutine sync.WaitGroup. En programmation simultanée, sync.WaitGroup est un mécanisme de synchronisation très utile qui peut attendre la fin de l'exécution d'un groupe de goroutines. Cependant, nous devons parfois écrire les résultats sur un chan une fois que la goroutine a terminé son exécution pour être consommés par d'autres goroutines. Cet article présentera en détail comment implémenter cette fonction dans la goroutine sync.WaitGroup, jetons un coup d'oeil !

Contenu de la question

Je reçois une liste d'éléments provenant d'un point de terminaison d'API. Ensuite, pour chaque projet, je fais une autre requête API pour obtenir des données sur le projet individuel.

Je ne peux pas faire une deuxième requête API à chaque projet en même temps car mon jeton API est limité en débit et si je fais trop de requêtes en même temps, je suis limité.

Cependant, les données de réponse initiales de l'API peuvent être divisées en plusieurs pages, ce qui me permet de traiter des pages de données simultanément.

Après quelques recherches, le code ci-dessous fait exactement ce que je veux :

func main() {
    // pretend paginated results from initial API request
    page1 := []int{1, 2, 3}
    page2 := []int{4, 5, 6}
    page3 := []int{7, 8, 9}
    pages := [][]int{page1, page2, page3}

    results := make(chan string)

    var wg sync.WaitGroup
    for i := range pages {
        wg.Add(1)
        go func(i int) {
            defer wg.Done()
            for j := range pages[i] {
                // simulate making additional API request and building the report
                time.Sleep(500 * time.Millisecond)

                result := fmt.Sprintf("Finished creating report for %d", pages[i][j])
                results <- result
            }

        }(i)
    }

    go func() {
        wg.Wait()
        close(results)
    }()

    for result := range results {
        fmt.Println(result)
    }
}

Je veux comprendre pourquoi ça marche :

go func() {
    wg.Wait()
    close(results)
}()

Ma première tentative a échoué - je pensais pouvoir lire le résultat pendant wg.Wait() 之后遍历通道,并且我会在结果写入 results la canalisation.

func main() {
    // pretend paginated results from initial API request
    page1 := []int{1, 2, 3}
    page2 := []int{4, 5, 6}
    page3 := []int{7, 8, 9}
    pages := [][]int{page1, page2, page3}

    results := make(chan string)

    var wg sync.WaitGroup
    for i := range pages {
        wg.Add(1)
        go func(i int) {
            defer wg.Done()
            for j := range pages[i] {
                // simulate making additional API request and building the report
                time.Sleep(500 * time.Millisecond)

                result := fmt.Sprintf("Finished creating report for %d", pages[i][j])
                results <- result
            }

        }(i)
    }

    // does not work
    wg.Wait()
    close(results)

    for result := range results {
        fmt.Println(result)
    }
}

Solution

Lors de votre premier essai :

  1. La goroutine principale fait que 3 goroutines mettent des valeurs dans le canal de résultat.
  2. La coroutine principale attend que toutes les coroutines soient terminées.
  3. L'une des goroutines met une valeur dans le canal de résultat et remplit le canal (la taille du canal est de 1 chaîne).
  4. Maintenant, les trois goroutines ne peuvent plus mettre de valeurs dans le canal de résultats et se mettre en veille jusqu'à ce que le canal de résultats soit libéré.
  5. Tous les goroutines sont en état de veille. Vous êtes dans une impasse.

Au deuxième essai :

  1. La goroutine principale contient 4 goroutines.
  2. 3 goroutines pour mettre des valeurs dans les canaux de résultats.
  3. L'autre goroutine (je l'appellerai la 4ème) attend la fin de ces 3 goroutines.
  4. En même temps, la coroutine principale attend la valeur dans le canal de résultat (boucle for)
  5. Dans ce cas, si l'une des goroutines met une valeur dans le canal de résultat, elle bloque les trois goroutines restantes ; la goroutine principale retire la valeur du canal de résultat, débloquant ainsi les autres goroutines.
  6. Donc les 3 goroutines mettent leurs valeurs respectives et terminent
  7. Puis la quatrième goroutine ferme la chaîne
  8. La Goroutine principale termine sa boucle for.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer