Während Ihre Lösung funktioniert, bin ich nicht zufrieden damit.
Erstens, die Tatsache, dass Sie die Kanalgröße ändern müssen, damit es funktioniert, zeigt an, dass ein potenzielles Problem/Fehler vorliegt. Nun müssen Sie jedes Mal, wenn Sie einen weiteren doSomething
starten wollen, daran denken, die Länge des Kanals zu ändern.
Zweitens warten Sie, bis alle goroutines beendet sind, bevor Sie vom Kanal lesen. Dies ist eine Art "Verschwendung", da einer der Hauptpunkte der Bereichsschleife über einen Kanal darin besteht, dass Sie nicht warten müssen, bis alle Elemente generiert sind (in den Kanal geschrieben), Sie können die Elemente sofort verarbeiten von ihnen sind bereit.
So würde ich Ihren Code als so etwas wie
func main() {
c := make(chan int)
var wg sync.WaitGroup
wg.Add(3)
go func() {
doSomething(c)
defer wg.Done()
}()
go func() {
doSomething(c)
defer wg.Done()
}()
go func() {
doSomething(c)
defer wg.Done()
}()
go func() {
wg.Wait()
defer close(c)
}()
for v := range c {
fmt.Print(v)
}
}
func doSomething(c chan<- int) {
c <- 1
}
https://play.golang.org/p/T3dfiztKot
Hinweis schreiben, wie das Warten und den Kanal zu schließen ist jetzt in einem eigenen goroutine - das Iterieren über den Kanal starten können (die ist jetzt ungepuffert!) sofort.
Ich änderte auch den Code, so dass die WaitGroup
nie den Bereich, in dem es erklärt wird (dh es wird nicht als Parameter verwendet), das ist meine persönliche Vorliebe. Ich glaube, es macht den Code einfacher zu folgen und zu verstehen.
Ich dachte, Sie können nicht über den Kanal reichen, bis der Kanal geschlossen ist. Vielleicht irre ich mich, aber das ist, was es hier sagt http://guzalexander.com/2013/12/06/golang-channel-tutorial.html "Wie oben erwähnt, wird der Bereich funktionieren, bis der Kanal explizit geschlossen wird".In diesem Fall müssen wir darauf warten, dass die andere Goroutine trotzdem ausgeführt wird. – tabiul
Sie missverstanden - der Punkt ist, dass die Schleife nicht enden würde, bis der Kanal geschlossen ist. Wenn der Kanal also nie geschlossen wird, hat man eine Endlosschleife (es würde auf das nächste Element oder das Schließen des Kanals warten). – ain
oh ok, du meinst also der for-Bereich wird blockieren bis der Kanal geschlossen ist. Ich denke dann ist deine Lösung besser – tabiul