GoLang教程中的死锁错误

I'm trying to do this tutorial -

https://tour.golang.org/concurrency/8

This is my code

// Walk walks the tree t sending all values
// from the tree to the channel ch.
func Walk(t *tree.Tree, ch chan int) {
    if t != nil {
        Walk(t.Left, ch)
        ch <- t.Value
        Walk(t.Right,ch)
    }
}

// Same determines whether the trees
// t1 and t2 contain the same values.
func Same(t1, t2 *tree.Tree) bool {
    ch1 := make(chan int)
    ch2 := make(chan int)
    go Walk(t1, ch1)
    go Walk(t2, ch2)
    for i:= range ch1 {
        if i != <-ch2 {

            return false
        }
    }


    return true

}

func main() {
    isSame := Same(tree.New(1), tree.New(1))    
    if isSame {
        fmt.Println("SAME")
    } else {
        fmt.Println("DIFF")
    }
}

But I get this error-

fatal error: all goroutines are asleep - deadlock!

It worked once, and then I ran it again and it stopped working...either that or I'm crazy.

What's going on?

The problem is that you never close ch1, so your for i:= range ch1 loop never finishes; it just reads until there are no values in the channel, and then it blocks. At this point, there will be only one goroutine, and it's blocked listening to the empty channel, so Go will abort with the message you see. (Similarly, you never close ch2, but in your case that doesn't happen to matter. That would cause a deadlock if ch2 ever had fewer values than ch1.)

To be honest, I'm not sure exactly what solution the "Tour of Go" folks had in mind.

One option, which would work but is totally cheating, is to hard-code the fact that you'll only see ten values:

for i := 0; i < 10; i++ {
    if <-ch1 != <-ch2 {
        return false
    }
}

A better option is for Same to use anonymous functions that invoke Walk and then close the channel:

go func() {
    Walk(t1, ch1)
    close(ch1)
}()

(or you could use a non-anonymous function for that; call it walkAndClose or something).

Incidentally, your Same function assumes that the two trees have the same sizes. If t1 has more elements, then t2 will be implicitly padded with zeroes at the end (since <-ch2 returns 0 once ch2 is closed and exhausted), and if t1 is shorter, then t2 will be implicitly truncated at the end. Maybe you're O.K. with making that assumption for the purposes of this exercise, but if you wanted Same to always return false for trees of different sizes, you could change your loop to:

for i := range ch1 {
    j, receivedJ := <-ch2
    if i != j || ! receivedJ {
        return false
    }
}
_, receivedJ := <-ch2
if receivedJ {
    return false
}

(where I've used the two-return-value form of <-ch2 to detect whether the channel has been closed and exhausted; receivedJ will be true if <-ch2 returned an actual value from the channel, and false if it returned a 0 by default).