Go 事情发生的顺序是什么?

Go 事情发生的顺序是什么?,go,Go,通过在官方网站上浏览围棋,我开始玩围棋 我只有编程方面的基本经验,但在进入频道页面时,我开始四处游荡,试图让我的头脑了解它,结果我很困惑 这就是我的代码: package main import "fmt" func sum(s []int, c chan int) { sum := 0 s[0] = 8 s = append(s, 20) fmt.Println(s) for _, v := range s { sum += v

通过在官方网站上浏览围棋,我开始玩围棋

我只有编程方面的基本经验,但在进入频道页面时,我开始四处游荡,试图让我的头脑了解它,结果我很困惑

这就是我的代码:

package main

import "fmt"

func sum(s []int, c chan int) {
    sum := 0
    s[0] = 8
    s = append(s, 20)
    fmt.Println(s)
    for _, v := range s {
        sum += v
    }
    c <- sum // send sum to c
}

func main() {
    s := []int{7, 2, 8, -9, 4, 0}

    c := make(chan int)
    go sum(s[:len(s)/2], c)
    fmt.Println(s[0])
    go sum(s[len(s)/2:], c)
    fmt.Println(s)
    x, y := <-c, <-c // receive from c

    fmt.Println(x, y, x+y)

    fmt.Println(s)
}
我知道,在创建一个切片时,你会得到一个底层数组,下面有所需的数字,然后将切片传递给一个函数,修改一个元素,修改底层数组,但我不确定goroutines的顺序是什么

它将第一个S[0]打印为7,即使之前的函数调用应该将其修改为8,所以我假设goroutines还没有运行? 然后在第二次goroutine函数调用后打印整个数组,并打印第一次函数调用期间所做的所有修改(将第一项修改为8,并附加20)。 然而,接下来的两行打印输出是来自函数内部的切片段的打印输出,这在逻辑上是因为我刚才说我看到了函数调用所做的修改,这意味着它们应该在该行之前打印出来

然后我不确定它是如何得到计算结果或数组的最终打印输出的

熟悉Go操作的人能解释一下这段代码的逻辑顺序吗

它将第一个S[0]打印为7,即使之前的函数调用应该将其修改为8,所以我假设goroutines还没有运行

是的,这个解释是正确的。(但不应这样做,见下一节)

然后在第二次goroutine函数调用后打印整个数组,并打印第一次函数调用期间所做的所有修改(将第一项修改为8,并附加20)

不,永远不要这样想。 此时应用程序的状态没有得到很好的定义。1) 您启动了修改状态的goroutine,但三个goroutine(主goroutine和手动启动的两个goroutine)之间绝对没有同步。2) 您的代码是racy,这意味着a)错误,racy程序永远不会正确,b)导致未定义的行为

然而,接下来的两行打印输出是来自函数内部的切片段的打印输出,这在逻辑上是因为我刚才说我看到了函数调用所做的修改,这意味着它们应该在该行之前打印出来

或多或少,如果你的程序不活泼(见上文)

你的代码在哪里?main.s是一个带有后备数组的切片,当你使用
go sum(…)
启动goroutines时,你可以将它再切片两次。两个子片共享相同的备份阵列。现在在goroutines中,您编写(
s[0]=8
)并将(
append(s,20)
)附加到此子片。从两个goroutine中删除,但不同步。第一个goroutine将使用第二个goroutine同时使用的足够大的支持数组来完成此追加。 这会导致并发写入而不同步到
main.s
的第四个元素,该元素是快速的,因此未定义


通过从通道读取两次(
,在第一次调用sum()时,您将传递一个新数组(切片的结果),因此sum()没有对原始数组的引用,因此无法更改它。嗯,大部分代码来自官方网站上的Go教程,试图解释编写goroutines和Channel的热门内容,一些额外的代码只是我试图了解它是如何工作的。看起来是时候让我花更多的时间阅读关于multi的内容了线程基础知识。@从教程中删除部分不是问题。问题在于您的修改引入了使教程代码无效的竞争。
7
[8 2 8 20 4 0]
[8 2 8 20]
[8 4 0 20]
26 32 58
[8 2 8 8 4 0]