func check(name string) string {
    resp, err := http.Get(endpoint + name)
    if err != nil {
        panic(err)
    }

    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)

    if err != nil {
        panic(err)
    }

    return string(body)

}

func worker(name string, wg *sync.WaitGroup, names chan string) {
    defer wg.Done()
    var a = check(name)
    names <- a
}

func main() {
    names := make(chan string)
    var wg sync.WaitGroup

    for i := 1; i <= 5; i++ {
        wg.Add(1)
        go worker("www"+strconv.Itoa(i), &wg, names)
    }
    fmt.Println(<-names)
}

Das erwartete Ergebnis wären 5 Ergebnisse, aber nur eines wird ausgeführt und der Prozess endet. Fehlt mir etwas? Neu zu gehen. Der Endpunkt ist eine generische API, die json zurückgibt

-1
James Rihno 19 Aug. 2020 im 07:21

2 Antworten

Beste Antwort

Sie haben 5 Goroutinen gestartet, aber nur eine Eingabe gelesen. Außerdem warten Sie nicht darauf, dass Ihre Goroutinen enden.

// If there are only 5 goroutines unconditionally, you don't need the wg
for i := 1; i <= 5; i++ {
        go worker("www"+strconv.Itoa(i),  names)
}
for i:=1;i<=5;i++ {
   fmt.Println(<-names)
}

Wenn Sie jedoch nicht wissen, auf wie viele Goroutinen Sie warten, ist die Wartegruppe erforderlich.

for i := 1; i <= 5; i++ {
      wg.Add(1)
      go worker("www"+strconv.Itoa(i), &wg, names)
}
// Read from the channel until it is closed
done:=make(chan struct{})
go func() {
   for x:=range names {
     fmt.Println(x)
    }
    // Signal that println is completed
    close(done)
}()

// Wait for goroutines to end
wg.Wait()
// Close the channel to terminate the reader goroutine
close(names)
// Wait until println completes
<-done
3
Burak Serdar 19 Aug. 2020 im 04:35

Sie starten 5 Goroutinen, lesen aber nur einmal aus dem names Kanal.

fmt.Println(<-names)

Sobald der erste Kanal gelesen wurde, wird main() beendet.
Das heißt, alles stoppt, bevor die Zeit zur Ausführung hat.

Weitere Informationen zu Kanälen finden Sie unter "Parallelität leicht gemacht" von Dave Cheney:

  • Wenn Sie auf das Ergebnis einer Operation warten müssen, ist es einfacher, dies selbst zu tun.
  • Lösen Sie Sperren und Semaphoren in der umgekehrten Reihenfolge, in der Sie sie erworben haben.
  • Kanäle sind keine Ressourcen wie Dateien oder Sockets. Sie müssen sie nicht schließen, um sie freizugeben.
  • Erwerben Sie Semaphoren, wenn Sie bereit sind, sie zu verwenden.
  • Vermeiden Sie das Mischen anonymer Funktionen und Goroutinen
  • Bevor Sie eine Goroutine starten, wissen Sie immer, wann und wie sie aufhört
2
VonC 19 Aug. 2020 im 06:01