How do goroutines work?

I followed the Go Tour and I get a little stuck when it comes to goroutines. I understand that they are very light and that every time a goroutine locks, another one starts, but I can’t understand how this example really works:

package main import ( "fmt" "time" ) func say(s string) { for i := 0; i < 5; i++ { time.Sleep(1000 * time.Millisecond) fmt.Println(s) } } func main() { go say("world") say("hello") } 

Playground

I understand that goroutine is run for the say function with the argument "peace", but as I understand it, it should print "peace" five times and "hello" once. However, I do not understand why the conclusion is as it is:

 hello world hello world hello world hello world hello 

From my limited understanding of flows from other languages, the output should be something like this:

 hello world world world world world 

or like this:

 world world world hello world world 

Why is the second line also executed five times? Is anything below the go statement classified as part of the go procedure?

Also the following slide shows that I cannot lower my head again:

 package main import "fmt" func sum(a []int, c chan int) { sum := 0 for _, v := range a { sum += v } c <- sum // send sum to c } func main() { a := []int{7, 2, 8, -9, 4, 0} c := make(chan int) go sum(a[:len(a)/2], c) go sum(a[len(a)/2:], c) x, y := <-c, <-c // receive from c fmt.Println(x, y, x+y) } 

Playground

Gorotin starts in the second half of the slice, and then the other for the first part of the slice, however, two different values ​​are assigned to the x and y values. As I see it, the sum function will send this sum to channel c , and then the next sum will send the sum to the same channel c , and how can two different values ​​be assigned to two variables? Should channel c have the same sum value?

I understand that this is a rather long question, but I could not find the answer to these questions.

+6
source share
2 answers

Why is the second line also executed 5 times?

The second line will print hello every second 5 times in the main() stream.
But at the same time, the first line of go say("world") will also print the world every five seconds in a separate goroutine.
Sleep ensures that each routine will give, allowing the other to resume.

Therefore, the conclusion:

 hello world hello world hello world hello world hello 

As I see it, the sum function will send the sum to channel c, and then the next sum will send the sum to the same channel c, and how can two different values ​​be assigned to two variables?

Since each send will be blocked on c until channel c is read.
Since there are two entries in c , you need to read:

  x, y := <-c, <-c // receive from c twice. 

The Assignement section in the Golang Spec allows you to assign a tuple if:

the number of operands on the left should equal the number of expressions on the right, each of which must be unique, and the expression nth on the right is assigned to the nth operand on the left.

+6
source

For the first function, you should see the values ​​in the presented VonC style. Reason hello prints 5 times since the say function prints things 5 ​​times. Imagine a program without goroutines. I think this does not guarantee that you will get hello and world completely interspersed, but I could be wrong.

The reason the channel works:

  • Golang allows multiple assignment as references to VonC
  • Channels empty out , i.e. when you assign c - x , it removes the first amount that was transferred to the channel, and when it assigns c - y , it goes into the second value (again, I think that the order is not a guarantee, since x can have the first half and y the second half of the amount or vice versa.

If you think of channels as a kind of lineup, I think that makes sense. Summing goroutines insert values ​​into the queue, and assignments sequentially expose the values.

+1
source

Source: https://habr.com/ru/post/974463/


All Articles