安排多个goroutine

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