Go channels: why two different outputs?

I am trying to understand the channels in Go. Here is a sample code:

package main import "fmt" func main() { m := make(map[int]string) m[2] = "First Value" c := make(chan bool) go func() { m[2] = "Second Value" c <- true }() fmt.Printf("1-%s\n", m[2]) fmt.Printf("2-%s\n", m[2]) _ = <-c fmt.Printf("3-%s\n", m[2]) fmt.Printf("4-%s\n", m[2]) } 

Sometimes the output of the above code was (result 1):

 1-First Value 2-First Value 3-Second Value 4-Second Value 

but sometimes I got (result 2):

 1-First Value 2-Second Value 3-Second Value 4-Second Value 

After changing c := make(chan bool) to c := make(chan bool, 1) the same thing happened: sometimes result 1, sometimes result 2.

Why?

+4
source share
2 answers

Your results make sense. Since go run run is independent of each other, you will never know when the normal procedure starts. As soon as the line

 m[2] = "Second Value" 
Performed

this will affect your normal procedure.

Therefore, when the first and second printouts of your program are performed on the line, you see the result as

 1-First Value 2-Second Value 3-Second Value 4-Second Value 

When you do not see another. Before the third print, you will be sure that the normal procedure is complete.

Just clean it even more if you change your program a bit like

 package main import "fmt" import "time" func main() { m := make(map[int]string) m[2] = "First Value" c := make(chan bool) go func() { m[2] = "Second Value" c <- true }() time.Sleep(time.Second) fmt.Printf("1-%s\n", m[2]) fmt.Printf("2-%s\n", m[2]) _ = <-c fmt.Printf("3-%s\n", m[2]) fmt.Printf("4-%s\n", m[2]) } 

Playground

Most likely you will get the following output

 1-Second Value 2-Second Value 3-Second Value 4-Second Value 

Hope this helps.

+4
source

In fact, you only encode that the third and fourth prints display the second value. When you change the channel to the presence of buffer 1, it does not change anything.

So, let's look at the first case. You have an unbuffered channel. When you start the routine, you change the contents of the map. But you do not know when the scheduler will launch it. That is why sometimes you see one result, and another - another result. A call: _ = <-c will ensure that the go procedure is running. Since this call will be blocked until the regular program actually writes anything on the channel. This is why you will never see the “First Meaning” in the last two prints.

When you use a buffer channel, the only thing that will change is that the go procedure will exit immediately after writing to the channel. Nothing more (read it on Effective Move ).

+2
source

All Articles