为什么这个示例将所有的goroutine都置于休眠状态?

huangapple go评论75阅读模式
英文:

Why does this example put all goroutines to sleep?

问题

// 蛋糕有一个私有的通道,用来告诉我们何时烤好了。
type Cake struct {
	BakingStatus chan string
}

// 烤箱立即通知每个蛋糕它已经烤好了。
func Oven(cakes chan *Cake) {
	for c := range cakes {
		c.BakingStatus <- "Done"
	}
}

func main() {
	cakes := make(chan *Cake)
	go Oven(cakes)

	myCake := &Cake{}
	cakes <- myCake       // 把蛋糕放进烤箱。
	<-myCake.BakingStatus // 等待蛋糕烤好。
    fmt.Println(myCake)
}

(这个例子很愚蠢和牵强,因为我为了这篇文章的目的将其简化到了绝对的最小程度。)

在我的脑海中,这个程序应该按照以下步骤工作:

  1. Oven 协程休眠,直到有东西被发送到 cakes 通道。
  2. myCake 被发送到 cakes 通道。
  3. Oven 协程接收到蛋糕。
  4. 主协程休眠,直到有东西被发送到 myCake.BakingStatus 通道。
  5. OvenmyCake.BakingStatus 通道发送一个值,并继续休眠。
  6. 主协程接收到 myCake 并打印它。

我能想象的唯一的问题是,在主协程发送蛋糕和 Oven 协程接收蛋糕之间有一个瞬间,它们都处于休眠状态。但是解决方案是什么呢?

英文:
// Cakes have a private channel to let us know when they&#39;re done.
type Cake struct {
	BakingStatus chan string
}

// Oven instantly notifies every cake that it is done.
func Oven(cakes chan *Cake) {
	for c := range cakes {
		c.BakingStatus &lt;- &quot;Done&quot;
	}
}

func main() {
	cakes := make(chan *Cake)
	go Oven(cakes)

	myCake := &amp;Cake{}
	cakes &lt;- myCake       // Put the cake in the oven.
	&lt;-myCake.BakingStatus // Wait for cake to be done.
    fmt.Println(myCake)
}

(This example is silly and contrived because I've pared it down to the absolute minimum for the sake of this post.)

In my head, this should work by the following steps:

  1. The Oven goroutine sleeps until something is sent on cakes.
  2. myCake is sent to cakes.
  3. The Oven goroutine receives the cake.
  4. The main goroutine sleeps until something is sent on myCake.BakingStatus.
  5. Oven sends a value to myCake.BakingStatus and goes back to sleep.
  6. The main goroutine receives myCake and prints it.

The only problem I can imagine is that there's a moment between the main goroutine sending and the Oven goroutine receiving the cake where they're both asleep. But then what is the solution?

答案1

得分: 4

"BakingStatus"未初始化。写入和读取空通道会永远阻塞。

myCake := &Cake{
    BakingStatus: make(chan string),
}
英文:

The "BakingStatus" is not initialized. Writing to and reading from a nil channel blocks forever.

	myCake := &amp;Cake{
		BakingStatus: make(chan string),
	}

huangapple
  • 本文由 发表于 2022年8月6日 03:27:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/73254481.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定