Reputation: 42999
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?
Upvotes: 2
Views: 146
Reputation: 620
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)
}
Upvotes: 4
Reputation: 9519
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.
Upvotes: 1
Reputation: 51587
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.
Upvotes: 1