Go 试图理解围棋中的“同步”。为什么这样做有效?

Go 试图理解围棋中的“同步”。为什么这样做有效?,go,Go,这个程序应该转到11,但有时它只打印1到10。修复代码并解释原因。这就是任务。 我试图理解为什么这段代码有效。如果只是因为我在向编译器添加汇编代码,所以Print会打印最后11个 所以我的问题是:为什么这段代码在我添加wg.Wait-after-close时会打印最后11个?我是我的头,我想添加wg.Wait before closech,这样通道就不会在我们完成之前关闭,但这会给我们一个死锁,因为我们将永远等待从通道接收更多的值 谢谢 原始代码没有与同步相关的代码 func main() {

这个程序应该转到11,但有时它只打印1到10。修复代码并解释原因。这就是任务。 我试图理解为什么这段代码有效。如果只是因为我在向编译器添加汇编代码,所以Print会打印最后11个

所以我的问题是:为什么这段代码在我添加wg.Wait-after-close时会打印最后11个?我是我的头,我想添加wg.Wait before closech,这样通道就不会在我们完成之前关闭,但这会给我们一个死锁,因为我们将永远等待从通道接收更多的值

谢谢

原始代码没有与同步相关的代码

func main() {

    ch := make(chan int)

    var wg sync.WaitGroup // added code

    wg.Add(1) // added code
    go Print(ch, &wg) // added code (&wg)

    for i := 1; i <= 11; i++ {
        ch <- i
    }

    close(ch)
    wg.Wait() // added code

}

// Print prints all numbers sent on the channel.
// The function returns when the channel is closed.
func Print(ch <-chan int, wg *sync.WaitGroup) { // added code (wg *sync.WaitGroup)
    for n := range ch { // reads from channel until it's closed
        fmt.Println(n)
    }
    wg.Done() // added code
}
如果没有wg.Wait,主goroutine可能会在第二个goroutine完成打印之前终止


您使用的是没有缓冲区的通道,因此每当主goroutine通过通道发送值时,goroutine都会接收该值。但是,这并不保证打印该值。主goroutine可以在打印完成之前启动,并可以终止程序。waitgroup必须确保主goroutine等待打印goroutine完成。

您在此处添加了汇编代码吗?我没有添加汇编代码。问题从一开始就出现了,因为在编译代码时,我们不知道代码是如何与机器代码组合在一起的。我的意思是,带点讽刺意味的是,我想理解为什么我的同步实现在理论上是有效的。可能吧,但我不这么认为,只是额外的代码增加了额外的机器代码行,所以主goroutine比从一开始就需要更长的时间。所以Print设法打印出最后一个数字。是的,到目前为止,我一直遵循这个推理。我明白为什么我想使用Wait,为什么我希望它出现在主goroutine中。问题是为什么Closech不关闭通道,所以在放置goroutine时完成打印goroutine。正如您所说,waitgroup是确保主goroutine等待打印goroutine完成所必需的,但是Close是使打印goroutine完成的原因。在我的脑海中,Close关闭通道,使打印goroutine返回,因此它的完成和主goroutine终止。但我们能知道我打印的所有内容吗?对无缓冲通道块的写入,直到有读取为止。关闭一个频道并不意味着什么。关闭通道后,主goroutine不会等待其他goroutine检测到。好的!这就是我问题的答案。谢谢