Yes, itβs complicated, but there are a few rules of thumb that should make things more clear.
- prefer to use formal arguments for channels that you pass go-routines instead of accessing channels in a global scope. You can get more compiler by checking this method, as well as better modularity.
- avoid reading and writing on the same channel in a certain routine (including the "main" one). Otherwise, deadlock is a much greater risk.
Here is an alternative version of your program that uses these two guides. This case shows a lot of writers and one reader on the channel:
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
It creates five routines that record one channel, each of which is recorded five times. The main routine reads all twenty-five messages - you may notice that the order in which they appear is often not sequential (i.e. concurrency).
This example demonstrates the function of the Go channels: perhaps several authors have one channel; Go will alternate messages automatically.
The same applies to one author and several readers on the same channel, as shown in the second example:
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()
This second example includes the wait imposed on the main goroutine, which would otherwise exit quickly and cause the other five goroutines to be completed earlier (thanks to olov for this correction).
In both examples, buffering was not required. As a general rule, viewing buffering as a performance enhancer is a good principle. If your program does not get into a dead end without buffers, it will also not be blocked by buffers (but the opposite is not always true). So, as another rule of thumb, start without buffering, and then add it as needed .