Maison  >  Article  >  développement back-end  >  Pourquoi une combinaison de « sync.WaitGroup » et de canaux entraîne-t-elle un blocage dans Go ?

Pourquoi une combinaison de « sync.WaitGroup » et de canaux entraîne-t-elle un blocage dans Go ?

Susan Sarandon
Susan Sarandonoriginal
2024-10-30 17:43:02929parcourir

Why Does a `sync.WaitGroup` and Channel Combination Lead to a Deadlock in Go?

Comprendre les blocages lors de l'utilisation de sync.WaitGroup et des canaux dans Go

Les développeurs rencontrent souvent des problèmes avec leurs applications Go qui ne se ferment jamais lorsqu'ils utilisent sync.WaitGroup et les chaînes. Cet article explore les raisons de ces blocages et propose une solution à l'aide du WaitGroup.

Considérez l'exemple de code fourni :

package main

import (
    "fmt"
    "io"
    "log"
    "net/http"
    "os"
    "sync"
)

var symbols = []string{
    "ASSA-B.ST",
    "ELUX-B.ST",
    "HM-B.ST",
}

func main() {

    fmt.Println("fetching quotes...")

    fetchedSymbols := make(chan string)
    var wg sync.WaitGroup
    wg.Add(len(symbols))

    for _, symbol := range symbols {
        go fetchSymbol(symbol, &wg, fetchedSymbols)
    }

    for response := range fetchedSymbols {
        fmt.Println("fetched " + response)
    }

    wg.Wait()

    fmt.Println("done")

}

func fetchSymbol(symbol string, wg *sync.WaitGroup, c chan<- string) {
    defer wg.Done()
    resp, err := http.Get("http://ichart.yahoo.com/table.csv?s=" + symbol + "&amp;a=0&amp;b=1&amp;c=2000")
    defer resp.Body.Close()

    if err != nil {
        log.Fatal(err)
    }

    out, err := os.Create("./stock-quotes/" + symbol + ".csv")
    defer out.Close()

    if err != nil {
        log.Fatal(err)
    }

    io.Copy(out, resp.Body)
    c <- symbol
}

Dans ce code, la boucle de plage sur les symboles récupérés bloquera le principal fonctionner indéfiniment. Pourquoi? Parce que le canal fetchedSymbols n’est jamais fermé. Pour résoudre cette impasse, le WaitGroup peut être utilisé pour signaler quand fermer le canal :

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

for response := range fetchedSymbols {
    fmt.Println("fetched " + response)
}

...

Comme le WaitGroup suit déjà lorsque toutes les goroutines sont terminées, il peut être exploité pour déclencher la fermeture du canal fetchedSymbols. , garantissant que la boucle de plage se termine correctement.

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:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn