goroutine的执行顺序

I am very new to golang.

My understanding is, All the go-routines will be executed concurrently. both anonymous goroutines will start executing concurrently. but when i run this code, It always prints

a=1 first executed
a=1 second executed
panic: b != 1

Shouldnt it print

a = 1
a = 1 first executed 
Response true
and so on

or

b =1 
b = 1 first executed 
Response true
and so on

Since after sending a value to the channel, the corresponding goroutine should block and wait for the receiver?

 func main() {
            var a, b int
            var c = make(chan bool)
            go func() {
                b = 1
                fmt.Println("b=1 first executed")
                c <- true
                fmt.Println("b=1 second executed")
                if a != 1 { // impossible
                    panic("a != 1") // will never happen
                }
                fmt.Println("b=1 third executed")
            }()
            go func() {
                a = 1
                fmt.Println("a=1 first executed")
                c <- true
                fmt.Println("a=1 second executed")
                if b != 1 { // impossible
                    panic("b != 1") // will never happen
                }
                fmt.Println("a=1 third executed")
            }()

            fmt.Println("Response ", <-c)
            fmt.Println("Main executed")
            }

I assuming you are running on Playground. There is one thing to keep in mind when using Go Playground: It has a fixed time and a fixed psedo-random generator.

That means, You can not use Playground to observe random outcomes. And the execuation order of Goroutine, or Go's Concurrency concept in general, is based on uniform psedo-random-ness.

Running your code on my terminal, it yields different results:

➜  basic1 GOMAXPROCS=1 ./basic1
a=1 first executed
a=1 second executed
a=1 third executed
Response  true
Main executed
➜  basic1 GOMAXPROCS=1 ./basic1
a=1 first executed
a=1 second executed
panic: b != 1

goroutine 6 [running]:
main.main.func2(0xc000012088, 0xc000054060, 0xc0000120a0)
        /mnt/f/home/leaf/spike/stackoverflow/concur/basic1/main.go:26 +0x13b
created by main.main
        /mnt/f/home/leaf/spike/stackoverflow/concur/basic1/main.go:20 +0xed
➜  basic1 GOMAXPROCS=1 ./basic1
a=1 first executed
a=1 second executed
a=1 third executed
b=1 first executed
Response  true
Main executed

But there's something more. As I have metioned, Go's concurrent excecution order is random. There is no guarantee which goes first, unless there is a synchronization.

Synchronizations includes channel communicating, and stuffs from sync.

There is only one synchronization happening in your code, which is communicating through c. It guarantees one thing: when the main() goroutine recieves its Response, at least one of the goroutines spawned there has printed its "excecuated".

There is no guarantee that which of one is execuated, nor both or only one is execuated, nor whether the goroutine hits the if statement containing panic first.

Edit:

Further reading:

The only synchronization between these tow goroutines ist via a send on c. As only one value is ever read from c only one of the two send operations c <- true goes through while the other blocks forever.

Lets assume the first goroutine runs first (by chance), and does the send and both Printlns while the second goroutine did not start executing at all. This is a valide mode of operation and will produce the output you see.

Your synchronization via c is not between the two anonymous goroutines, but between the goroutines and the outer f3 only.