Go tutorial: Channels, Buffered Channels tutorial

I am going through Go's official tutorial and have difficulty understanding the difference between Channel and Buffered Channels. The links to the tutorials are https://tour.golang.org/concurrency/2 and https://tour.golang.org/concurrency/3

In the Channel tutorial, Channel c first received the sum of [7, 2, 8] which is 17 and then received the sum of [-9, 4, 0] which is -5. When reading from c, it first output -5 to x and then 17 to y, in LIFO order:

package main

import "fmt"

func sum(s []int, c chan int) {
    sum := 0
    for _, v := range s {
        sum += v
    }
    c <- sum // send sum to c
}

func main() {
    s := []int{7, 2, 8, -9, 4, 0}

    c := make(chan int)
    go sum(s[:len(s)/2], c)
    go sum(s[len(s)/2:], c)
    x, y := <-c, <-c // receive from c

    fmt.Println(x, y, x+y)
}

(The above output is -5 17 12)

In the Buffered Channel tutorial, the output is 1 2, in FIFO order:

func main() {
    ch := make(chan int, 2)
    ch <- 1
    ch <- 2
    fmt.Println(<-ch)
    fmt.Println(<-ch)
}

Why are they different?

1 answer

  • answered 2018-04-14 14:26 Maruf Tuhin

    The chnnael c, in your 1st example of unbuffered channel, is not acting as LIFO.

    Actually it is happening because of go routines. The go routines executes concurrently.

    If you tweak your code to debug, add one extra line in sum to print the sum before sending to channel.

    package main
    
    import "fmt"
    
    func sum(s []int, c chan int) {
        sum := 0
        for _, v := range s {
            sum += v
        }
        fmt.Println("slice:", s)
        fmt.Println(sum)
        c <- sum         // send sum to c
    }
    
    func main() {
        s := []int{7, 2, 8, -9, 4, 0}
    
        c := make(chan int)
        go sum(s[:2], c)
        go sum(s[2:4], c)
        go sum(s[4:6], c)
        x, y, z := <-c, <-c, <-c // receive from c
        fmt.Println(x, y, z, x+y+z)
    }
    

    The output is:

    slice: [4 0]
    4
    slice: [7 2]
    9
    slice: [8 -9]
    -1
    4 9 -1 12
    

    So, you can see that x receives the 1st number that was sent through channel.

    Furthermore, unbuffered channels sends data directly to receiver.

    If you wanna know about the architecture of channels in go, you can watch this talk of gophercon-2017. I found this talk very helpful.