Send and receive operations on channel


Go‘s built-in channel type provides a handy method for communicating and synchronizing: The producer pushes data into channel and the consumer pulls data from it.

The send operation on channel is simple, as long as the filled-in stuff is a valid expression and matches the channel’s type:

  1. Channel <- Expression

Take the following code as an example:

  1. package main
  2. func send() int {
  3. return 2
  4. }
  5. func main() {
  6. ch := make(chan int, 2)
  7. ch <- 1
  8. ch <- send()
  9. }

Receive operation on channel pulls the value from the channel, and you can save it or discard it if you don’t care what you have got. Check the following example:

  1. package main
  2. import "fmt"
  3. func main() {
  4. ch := make(chan int)
  5. go func(ch chan int) {
  6. ch <- 1
  7. ch <- 2
  8. }(ch)
  9. <-ch
  10. fmt.Println(<-ch)
  11. }

The running result is 2, and that’s because the first value (1) is left out in <-ch statement.

Compared to its send sibling, the receive operation is a little tricky: in assignment and initialization, there will be another return value which indicates whether this communication is successful or not. And the idiom of this variable’s name is ok:

  1. v, ok := <- ch

The value of ok is true if the value received was delivered by a successful send operation to the channel, or false if it is a zero value generated because the channel is closed and empty. That means although the channel is closed, as long as there is still data in the channel, the receive operation can of course get things from it. See the following code:

  1. package main
  2. import "fmt"
  3. func main() {
  4. ch := make(chan int)
  5. go func(ch chan int) {
  6. ch <- 1
  7. ch <- 2
  8. close(ch)
  9. }(ch)
  10. for i := 1; i <= 3; i++ {
  11. v, ok := <- ch
  12. fmt.Printf("value is %d, ok is %v\n", v, ok)
  13. }
  14. }

The executing result is like this:

  1. value is 1, ok is true
  2. value is 2, ok is true
  3. value is 0, ok is false

We can see after func goroutine executes closing channel operation, the value of v got from channel is the zero value of integer type: 0, and ok is false.

Reference:
The Go Programming Language Specification.