将两个 fmt.printlns 与 go 例程一起使用时出现死锁?

我正在尝试学习围棋,并且正在操场上进行试验。我有一个非常简单的代码。我试图在 go 例程中同时使用 Structs 和 Slices。我不确定这是否是我会在生产中使用的东西,但它似乎有点不对劲,所以在这里:



func main() {

    routinemsg := make(chan []Person)

    routinemsg2 := make(chan []Person)


    // create the person records

    p1 := newPerson("john doe", 25)

    p2 := newPerson("dohn joe", 52)

    p3 := newPerson("bohn joo", 30)


    // send a slice of Person to the first routine

    go func() { routinemsg <- []Person{p1, p2} }()


    // retrieve the slice from the first routine[in the append]

    // append p3 to the slice retrieved from the first routine

    // send the new slice to the second routine

    go func() { routinemsg2 <- append(<-routinemsg, p3) }()

    

    // I am able to see the first Println but when I insert the second one I get a deadlock error

    // also, same error if I use one Println with 2 arguments.

    fmt.Println(<-routinemsg)

    fmt.Println(<-routinemsg2)

}

我听说过等待小组,但还不了解他们!所以,对我好点:D,谢谢你抽出时间


PIPIONE
浏览 83回答 2
2回答

LEATH

上只有一个发送操作routinemsg,但您有 2 个接收操作:一个在已启动的 goroutine 中,另一个在 goroutine 中main。一个发送的值只能被一个接收者接收一次。如果启动的 goroutine 从routinemsgfirst 接收,那么这将是一个死锁:接收将main永远阻塞。如果maingoroutine 将首先接收,那么启动的 goroutine 将永远阻塞(试图从它接收),因此它永远不会发送任何东西 on ,因此来自inroutinemsg2的接收也将永远阻塞:再次死锁。routinemsg2main删除fmt.Println(<-routinemsg)中的行main(),然后最终接收 fromroutinemsg2可以(最终)继续并打印包含p1,p2和 的切片p3:[{john&nbsp;doe&nbsp;25}&nbsp;{dohn&nbsp;joe&nbsp;52}&nbsp;{bohn&nbsp;joo&nbsp;30}]在Go Playground上尝试一下。

慕斯王

如果您使用如下所示的缓冲通道,&nbsp;&nbsp;&nbsp;&nbsp;buffered&nbsp;:=&nbsp;make(chan&nbsp;string,&nbsp;2) &nbsp;&nbsp;&nbsp;&nbsp;buffered&nbsp;<-&nbsp;"1" &nbsp;&nbsp;&nbsp;&nbsp;buffered&nbsp;<-&nbsp;"2" &nbsp;&nbsp;&nbsp;&nbsp;fmt.Println(<-buffered) &nbsp;&nbsp;&nbsp;&nbsp;fmt.Println(<-buffered)您可以从同一通道多次发送和接收值。但是,您仍然可以通过传递给make 的参数来限制发送和接收的次数!此外,对于缓冲通道,您将始终按照发送到通道的顺序接收值。因此,您从第二个接收器收到的第二个值将始终是发送到通道的第二个值。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go