goroutines如何运作?

Bul*_*ula 6 concurrency go goroutine

我正在关注Go Tour,当涉及到goroutines时我有点卡住了.我知道他们非常轻量级,每次goroutine阻止,另一个将开始,但我无法理解这个例子实际如何工作:

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")
}
Run Code Online (Sandbox Code Playgroud)

Playground

据我所知,一个goroutine是针对具有参数"world"的say函数启动的,但据我所知,应该打印"world"五次并且"hello"一次.但是我不明白为什么输出是这样的:

hello
world
hello
world
hello
world
hello
world
hello
Run Code Online (Sandbox Code Playgroud)

从我对其他语言的线程的有限理解,输出应该是这样的:

hello
world
world
world
world
world
Run Code Online (Sandbox Code Playgroud)

或者像这样:

world 
world
world
hello
world
world
Run Code Online (Sandbox Code Playgroud)

为什么第二行也执行五次?go语句下面的任何内容都会归类为go例程的一部分吗?

下一张幻灯片还显示了我无法再次回头看的内容:

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)
}
Run Code Online (Sandbox Code Playgroud)

Playground

甲够程开始切片的后半部分,然后另外一个切片的第一部分,但是这些值xy已被分配了两个不同的值.我看到它的方式sum函数会将它的总和发送到通道c,然后下一个sum将它的总和发送到同一个通道,c那么如何为两个变量分配两个不同的值?渠道不应该c只有一个单一的sum价值吗?

我很欣赏这是一个很长的问题,但我无法找到这些问题的答案.

Von*_*onC 5

为什么第二行也执行5次?

第二行将hellomain()线程中每隔5次打印一次.
同时第一行go say("world")也会在一个单独的goroutine中每隔五秒打印一次世界.
Sleep确保每个例程的产量,让对方恢复.

因此输出:

hello
world
hello
world
hello
world
hello
world
hello
Run Code Online (Sandbox Code Playgroud)

我看到它的方式sum函数会将它的总和发送到通道c,然后下一个和将它的总和发送到同一个通道c,那么如何为这两个变量分配两个不同的值?

因为每个发送都将阻塞,c直到c读取通道.
由于有两个写入c,您需要阅读:

 x, y := <-c, <-c // receive from c twice.
Run Code Online (Sandbox Code Playgroud)

Golang SpecAssignement部分允许在以下情况下进行元组赋值:

左边的操作数必须等于右边的表达式数,每个表达式必须是单值的,nth右边的表达式分配给左边的第n个操作数.