package main
import "fmt"
func square(c chan int) {
fmt.Println("[square] reading (4)")
num := <-c
fmt.Println("[square] calc (5)")
c <- num * num
fmt.Println("back from [square] (10)")
}
func cube(c chan int) {
fmt.Println("[cube] reading (3)")
num := <-c
fmt.Println("[cube] calc (11)")
c <- num * num * num
fmt.Println("back from [cube] (12)")
}
func main() {
fmt.Println("[main] main() started (1)")
squareChan := make(chan int)
cubeChan := make(chan int)
go square(squareChan)
go cube(cubeChan)
testNum := 3
fmt.Println("[main] sent testNum to squareChan (2)")
squareChan <- testNum
fmt.Println("[main] resuming (6)")
fmt.Println("[main] sent testNum to cubeChan (7)")
cubeChan <- testNum // why doesn't block here?
fmt.Println("[main] resuming (8)")
fmt.Println("[main] reading from channels (9)")
squareVal, cubeVal := <-squareChan, <-cubeChan
fmt.Println("[main] waiting calculating (13)")
fmt.Println("[main] results: ", squareVal, cubeVal)
fmt.Println("[main] main() stopped")
}
output:
[main] main() started (1)
[main] sent testNum to squareChan (2)
[cube] reading (3)
[square] reading (4)
[square] calc (5)
[main] resuming (6)
[main] sent testNum to cubeChan (7)
[main] resuming (8)
[main] reading from channels (9)
back from [square] (10)
[cube] calc (11)
back from [cube] (12)
[main] waiting calculating (13)
[main] results: 9 27
[main] main() stopped
In the code given above, I think the main()
routine should be blocked after cubeChan <- testNum
, then cube
routine should be scheduled, which means the output [cube] calc (11)
ought to be prior to [main] resuming (8)
. But after executing on Playground, I'm so confused by the output.
Could anyone tell me if I misunderstand anything?
I think the main() routine should be blocked after cubeChan <- testNum
it does block, but at these:
squareVal, cubeVal := <-squareChan, <-cubeChan
^ ^
if either squareChan
or cubeChan
doesn't receive any values in other routines, that line will become deadlock, modify cube()
like below to see the effect:
func cube(c chan int) {
fmt.Println("[cube] reading (3)")
_ = <-c
fmt.Println("[cube] calc (11)")
// c <- num * num * num
fmt.Println("back from [cube] (12)")
}
I think you're misunderstanding con-current code.
But, channels only block flow if they have nothing to output or if they're full. And channels can only get full if you specify a size.
I also dont recommend using the same channel for input and output for a function
With your current method you could run into trouble here
cubeChan <- testNum
fmt.Println("[main] resuming (8)")
fmt.Println("[main] reading from channels (9)")
squareVal, cubeVal := <-squareChan, <-cubeChan
If your cube function is too slow for any possible number of reasons, the testNum that you add onto the cubechan could be instantly taken off with this line here
squareVal, cubeVal := <-squareChan, <-cubeChan