Так, це складно, але є кілька ескізних правил, які повинні зробити речі набагато простішими.
- віддайте перевагу використанню формальних аргументів для каналів, які ви передаєте go-процедурам, замість доступу до каналів у глобальній області. Ви можете отримати більше компілятора, перевіряючи таким чином, і кращу модульність.
- уникайте як читання, так і письма на одному каналі в певній рутинній програмі (включаючи «основну»). В іншому випадку глухий кут є набагато більшим ризиком.
Ось альтернативна версія вашої програми із застосуванням цих двох рекомендацій. Цей випадок демонструє багато авторів та одного читача на каналі:
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
Він створює п’ять рутинних процедур запису в один канал, кожен пише п’ять разів. Основна рутина читає всі двадцять п’ять повідомлень - ви можете помітити, що порядок їх появи часто не є послідовним (тобто паралельність очевидна).
Цей приклад демонструє особливість каналів Go: можна мати декілька авторів, які спільно використовують один канал; Go автоматично чергуватиме повідомлення.
Те саме стосується одного автора та кількох читачів на одному каналі, як видно з другого прикладу тут:
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()
Цей другий приклад включає очікування, накладене на основну програму, яка в іншому випадку негайно вийде і призведе до того, що інші п’ять програм будуть достроково припинені (дякую olov за цю корекцію) .
В обох прикладах буферизація не потрібна. Як правило, хорошим принципом вважати буферизацію лише як покращення продуктивності. Якщо ваша програма не блокує ситуацію без буферів, вона також не заблокує роботу з буферами (але зворотне не завжди відповідає дійсності). Отже, як ще одне правило, починайте без буферизації, а потім додайте його пізніше за необхідності .
original, hi from 4...