Why does this example put all goroutines to sleep?

// Cakes have a private channel to let us know when they'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 <- "Done"
    }
}

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

    myCake := &Cake{}
    cakes <- myCake       // Put the cake in the oven.
    <-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?

>Solution :

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

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

Leave a Reply