It entirely depends on OS scheduling. The results of the above code would not be always the same.
main() started
After 1, capacity 1
After 2, capacity 2
After 3, capacity 3
1
2
3
4
After 4, capacity 0
After 5, capacity 0
After 6, capacity 1
After 7, capacity 2
After 8, capacity 3
5
6
7
8
9
After 9, capacity 0
After 10
main() stopped
This result might be the same as you saw in the playground. But, it is unpredictable because we can't determine how OS schedule the execution order of goroutines.
If I run this code in my local machine, It will be different every time I execute it. See below:
First run
main() started
After 1, capacity 1
After 2, capacity 1
After 3, capacity 2
1
2
3
4
After 4, capacity 3
After 5, capacity 0
5
After 6, capacity 0
After 7, capacity 1
After 8, capacity 2
After 9, capacity 3
6
7
8
9
10
After 10
main() stopped
Second run
main() started
After 1, capacity 1
After 2, capacity 2
1
2
3
After 3, capacity 2
After 4, capacity 0
4
5
After 5, capacity 1
After 6, capacity 0
After 7, capacity 1
After 8, capacity 2
6
7
8
9
After 9, capacity 3
After 10
main() stopped
10
So answers to your questions would be
Receiving the channel (for 4) just was executed before fmt.Printf
in the main function. It could be different every execution. Try it on your local machine.
Similar to 1. It just read by range
before len(c)
.
The main goroutine exited before reading the 10 from the channel. In this case, you should wait for all items in the channel will be read using some techniques such as time sleeping, wait group of sync package or another channel.
You can see how that program works by inserting the time.Sleep(time.Second)
between the lines you want to inspect.
For example, if you sleep for 1 second before fmt.Println("main() stopped")
, you can see always the 10
echo because the main goroutine will be waiting for a second. (1 second is big enough for reading an item from the channel)
package main
import "fmt"
import "time"
func echo(c chan int) {
for num := range c {
fmt.Println(num)
}
fmt.Println("Done iterating")
}
func main() {
fmt.Println("main() started")
c := make(chan int, 3)
go echo(c)
c <- 1
fmt.Printf("After 1, capacity %v
",len(c))
c <- 2
fmt.Printf("After 2, capacity %v
",len(c))
c <- 3
fmt.Printf("After 3, capacity %v
",len(c))
c <- 4 // blocks here
fmt.Printf("After 4, capacity %v
",len(c))
c <- 5
fmt.Printf("After 5, capacity %v
",len(c))
c <- 6
fmt.Printf("After 6, capacity %v
",len(c))
c <- 7
fmt.Printf("After 7, capacity %v
",len(c))
c <- 8
fmt.Printf("After 8, capacity %v
",len(c))
c <- 9
fmt.Printf("After 9, capacity %v
",len(c))
c <- 10
fmt.Printf("After 10
")
time.Sleep(time.Second)
fmt.Println("main() stopped")
}