2

I have this code from Go tour:

func sum(s []int, c chan int) {
    sum := 0
    for _, v := range s {
        sum += v
    }
    fmt.Printf("Sending %d to chan\n", sum)
    c <- sum // send sum to c
}

func main() {
    s := []int{2, 8, -9, 4, 0, 99}
    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)
}

Produces this output:

Sending 1 to chan
Sending 103 to chan
1 103 104

In this, x gets the second sum and y gets the first sum. Why is the order reversed?

codeforester
  • 39,467
  • 16
  • 112
  • 140
  • 3
    The TL;DR for the multiple answers below is: once data gets *into* the channel, it's ordered, but you're doing the put-data-into-channel in goroutine execution order, which is not controlled, possibly parallel, and in any case not very predictable. – torek Oct 20 '19 at 07:50

3 Answers3

4

Similar to goroutines order of execution

If you run it multiple times, it may give different result. When I run this I get:

Sending 103 to chan
Sending 1 to chan
103 1 104

If you want result to be deterministic. You may use two channels:

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

    c1 := make(chan int)
    c2 := make(chan int)
    go sum(s[len(s)/2:], c1)
    go sum(s[:len(s)/2], c2)

    x, y := <-c1, <-c2 // receive from c

    fmt.Println(x, y, x+y)
}
codeforester
  • 39,467
  • 16
  • 112
  • 140
Devendra Mukharaiya
  • 480
  • 1
  • 5
  • 19
1

There are no guarantees in the execution ordering of goroutines. When you start multiple goroutines, they may or may not execute in the order you expect them unless there are explicit synchronizations between them, such as channels or other synchronization primitives.

In your case, the second goroutine writes the channel before the first can, because there is no mechanism to enforce ordering between the two goroutines.

Burak Serdar
  • 46,455
  • 3
  • 40
  • 59
1

The golang spec says about the channels:

Channels act as first-in-first-out queues. For example, if one goroutine sends values on a channel and a second goroutine receives them, the values are received in the order sent.

If you combine the above statement with the arbitrary order of the goroutines execution it could lead to arbitrary order of enqueuing items to channel.


NB: A channel is an abstraction of the CSP.

Johnny
  • 8,939
  • 2
  • 28
  • 33