Tak, to skomplikowane, ale istnieje kilka praktycznych zasad, które powinny sprawić, że wszystko będzie o wiele prostsze.
- wolą używać formalnych argumentów dla kanałów które przekazujesz do procedur go, zamiast uzyskiwać dostęp do kanałów o zasięgu globalnym. W ten sposób możesz uzyskać więcej sprawdzania kompilatora, a także lepszą modułowość.
- unikaj czytania i pisania na tym samym kanale w ramach określonej procedury go (w tym „głównej”). W przeciwnym razie impas jest znacznie większym ryzykiem.
Oto alternatywna wersja twojego programu, stosując te dwie wskazówki. Ten przypadek pokazuje wielu pisarzy i jednego czytelnika na kanale:
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
Tworzy pięć podprogramów go zapisujących na jednym kanale, z których każda zapisuje pięć razy. Główna procedura go odczytuje wszystkie dwadzieścia pięć komunikatów - możesz zauważyć, że kolejność, w jakiej się pojawiają, często nie jest sekwencyjna (tj. Współbieżność jest oczywista).
Ten przykład demonstruje funkcję kanałów Go: możliwe jest współdzielenie jednego kanału przez wielu autorów; Go automatycznie przepleci wiadomości.
To samo dotyczy jednego pisarza i wielu czytelników na jednym kanale, jak widać w drugim przykładzie tutaj:
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()
Ten drugi przykład obejmuje oczekiwanie nałożone na główną gorutynę, która w przeciwnym razie natychmiast zakończyłaby pracę i spowodowała wcześniejsze zakończenie pozostałych pięciu gorutyn (dzięki olovowi za tę korektę) .
W obu przykładach buforowanie nie było potrzebne. Ogólnie rzecz biorąc, dobrą zasadą jest postrzeganie buforowania tylko jako środka zwiększającego wydajność. Jeśli twój program nie blokuje się bez buforów, nie blokuje się również z buforami (ale odwrotność nie zawsze jest prawdą). Tak więc, zgodnie z kolejną praktyczną zasadą, zacznij bez buforowania, a następnie dodaj je później, w razie potrzeby .
original, hi from 4
...