go语言中的递归函数

时间:2012-11-12 04:11:45

标签: go

我几天前开始学习语言。当我试着开始写一些有趣的代码时,我被一种奇怪的行为所困扰。

package main

import "fmt"

func recv(value int) {
    if value < 0 {
        return
    }

    fmt.Println(value)
    go recv(value-1)
}

func main() {
    recv(10)
}

当我运行上面的代码时,只打印10。如果在致电go之前删除recv,则会打印100。我相信我在这里滥用常规,但我无法理解为什么它以这种方式开始一个例行程序失败。

3 个答案:

答案 0 :(得分:16)

当main函数返回时,Go不会等待任何仍然存在的goroutine完成,而是退出。

recv将在第一次“迭代”之后返回main,因为main没有更多事情要做,程序将终止。

这个问题的一个解决方案是建立一个通道,表明所有工作都已完成,如下所示:

package main

import "fmt"

func recv(value int, ch chan bool) {
    if value < 0 {
        ch <- true
        return
    }

    fmt.Println(value)
    go recv(value - 1, ch)
}

func main() {
    ch := make(chan bool)
    recv(10, ch)

    <-ch
}

此处,recv将在返回前发送一个布尔值,main将在该频道上等待该消息。

对于程序的逻辑,使用什么类型或特定值无关紧要。 booltrue只是一个简单的例子。如果您想提高效率,使用chan struct{}代替chan bool将为您节省额外的字节,因为空结构不使用任何内存。

答案 1 :(得分:10)

sync.Waitgroup是另一种解决方案,专门用于等待任意数量的goroutine运行。

package main

import (
    "fmt"
    "sync"
)

func recv(value int, wg *sync.WaitGroup) {
    if value < 0 {
        return
    }

    fmt.Println(value)

    wg.Add(1) // Add 1 goroutine to the waitgroup.

    go func() {
        recv(value-1, wg)
        wg.Done() // This goroutine is finished.
    }()
}

func main() {
    var wg sync.WaitGroup
    recv(10, &wg)

    // Block until the waitgroup signals
    // all goroutines to be finished.
    wg.Wait()
}

答案 2 :(得分:-2)

我这样做也工作过。怎么样?

package main

import "fmt"

func recv(value int) {
    if value < 0 {
      return
    }

    fmt.Println(value)
    recv(value - 1)
}

func main() {
  recv(10)
}