Ja, es ist kompliziert, aber es gibt ein paar Faustregeln, nach denen sich die Dinge viel einfacher anfühlen sollten.
- Verwenden Sie lieber formale Argumente für die Kanäle, die Sie an Go-Routinen übergeben, als auf Kanäle im globalen Bereich zuzugreifen. Auf diese Weise können Sie mehr Compiler überprüfen und auch die Modularität verbessern.
- Vermeiden Sie sowohl das Lesen als auch das Schreiben auf demselben Kanal in einer bestimmten Go-Routine (einschließlich der ' Haupt'-Routine ). Andernfalls ist Deadlock ein viel größeres Risiko.
Hier ist eine alternative Version Ihres Programms, die diese beiden Richtlinien anwendet. Dieser Fall zeigt viele Autoren und einen Leser auf einem Kanal:
c := make(chan string)
for i := 1; i <= 5; i++ {
go func(i int, co chan<- string) {
for j := 1; j <= 5; j++ {
co <- fmt.Sprintf("hi from %d.%d", i, j)
}
}(i, c)
}
for i := 1; i <= 25; i++ {
fmt.Println(<-c)
}
http://play.golang.org/p/quQn7xePLw
Es werden die fünf Go-Routinen erstellt, die in einen einzelnen Kanal schreiben, wobei jeder fünfmal schreibt. Die Hauptroutine liest alle fünfundzwanzig Nachrichten - Sie können feststellen, dass die Reihenfolge, in der sie angezeigt werden, häufig nicht sequentiell ist (dh die Parallelität ist offensichtlich).
Dieses Beispiel zeigt eine Funktion von Go-Kanälen: Es ist möglich, dass mehrere Autoren einen Kanal gemeinsam nutzen. Go verschachtelt die Nachrichten automatisch.
Gleiches gilt für einen Schreiber und mehrere Leser auf einem Kanal, wie im zweiten Beispiel hier gezeigt:
c := make(chan int)
var w sync.WaitGroup
w.Add(5)
for i := 1; i <= 5; i++ {
go func(i int, ci <-chan int) {
j := 1
for v := range ci {
time.Sleep(time.Millisecond)
fmt.Printf("%d.%d got %d\n", i, j, v)
j += 1
}
w.Done()
}(i, c)
}
for i := 1; i <= 25; i++ {
c <- i
}
close(c)
w.Wait()
Dieses zweite Beispiel enthält eine Wartezeit für die Hauptgoroutine, die andernfalls sofort beendet würde und dazu führen würde, dass die anderen fünf Goroutinen vorzeitig beendet werden (danke an olov für diese Korrektur) .
In beiden Beispielen war keine Pufferung erforderlich. Es ist im Allgemeinen ein gutes Prinzip, die Pufferung nur als Leistungsverbesserer anzusehen. Wenn Ihr Programm ohne Puffer nicht blockiert, blockiert es auch nicht mit Puffern (aber das Gegenteil ist nicht immer der Fall). So, wie eine andere Faustregel starten , ohne Pufferung dann fügen Sie später nach Bedarf .
original, hi from 4
...