如何在递归函数中关闭通道

I tried to find a similar question but I couldn't, so here I am asking:


I'm using close(ch) inside a recursive function. I need to close channel to terminate a range loop. However, since the function is recursive, the close is run multiple times which gives me:

panic: close of closed channel

If I comment-out the close(ch) statement, I receive:

fatal error: all goroutines are asleep - deadlock!

Please find below my code:

package main

import "golang.org/x/tour/tree"
import "fmt"

// Walk walks the tree t sending all values
// from the tree to the channel ch.
func Walk(t *tree.Tree, ch chan int) {
    ch<-(t.Value)
    if t.Left != nil { Walk(t.Left, ch) }
    if t.Right != nil { Walk(t.Right, ch) }
    close(ch) // => How to close a channel inside recursive function? ***
    return
}

func main() {
    ch := make(chan int)
    go Walk(tree.New(1), ch)
    for i := range ch {
        fmt.Print(i, " ")
    }
}

Close the channel outside of the recursive function:

func Walk(t *tree.Tree, ch chan int) {
    ch<-(t.Value)
    if t.Left != nil { Walk(t.Left, ch) }
    if t.Right != nil { Walk(t.Right, ch) }
}

func main() {
    ch := make(chan int)
    go func() {
        defer close(ch)
        Walk(tree.New(1), ch)
    }()
    for i := range ch {
        fmt.Print(i, " ")
    }
}

I find this way of writing it to be much cleaner

func Walk(t *tree.Tree, ch chan int){
    WalkRecurse(t, ch)
    close(ch)
}
func WalkRecurse(t *tree.Tree, ch chan int){
    if t.Left != nil {
        WalkRecurse(t.Left, ch)
    }
    ch <- t.Value
    if t.Right != nil {
        WalkRecurse(t.Right, ch)
    }
}
func main(){
   ch := make(chan int)
   go Walk(tree.New(1), ch)
   for i := range ch {
      fmt.Println(i)
   }
}