将自身称为 goroutine 的 golang 递归函数无法按预期工作
golang recursive function calling itself as a goroutine doesn't work as expected
此递归函数按预期工作(returns 5 行,数字 5 到 1):
package main
import (
"fmt"
)
func recur(iter int) {
if iter <= 0 {
return
}
fmt.Println(iter)
recur(iter-1)
}
func main() {
recur(5)
}
这个没有(returns 只有 1 行数字 5):
package main
import (
"fmt"
)
func recur(iter int) {
if iter <= 0 {
return
}
fmt.Println(iter)
go recur(iter-1)
}
func main() {
recur(5)
}
不同的是,在第二种实现中,function调用自己作为一个goroutine。 (第 go recur(iter-1)
行)
有人可以解释这种行为吗?
如果您将所有内容设为异步,main
中就没有任何内容可以等待。您必须显式地等待 go 例程,以便您的程序不会在递归过程完成之前退出。
使用sync.WaitGroup
or something similar for synchronization. Example (On Play):
func recur(iter int, g *sync.WaitGroup) {
defer g.Done()
if iter <= 0 {
return
}
fmt.Println(iter)
go recur(iter-1, g)
}
func main() {
g := &sync.WaitGroup{}
runs := 5
g.Add(runs)
recur(runs, g)
g.Wait()
}
在所有 goroutine 完成之前,您的程序正在退出。最简单的看这部作品的方法如下
package main
import (
"fmt"
"time"
)
func recur(iter int) {
if iter <= 0 {
return
}
fmt.Println(iter)
go recur(iter - 1)
}
func main() {
recur(5)
time.Sleep(time.Second)
}
但是,您可能希望将 sync.WaitGroup
传递给您的函数,而不是休眠。
此递归函数按预期工作(returns 5 行,数字 5 到 1):
package main
import (
"fmt"
)
func recur(iter int) {
if iter <= 0 {
return
}
fmt.Println(iter)
recur(iter-1)
}
func main() {
recur(5)
}
这个没有(returns 只有 1 行数字 5):
package main
import (
"fmt"
)
func recur(iter int) {
if iter <= 0 {
return
}
fmt.Println(iter)
go recur(iter-1)
}
func main() {
recur(5)
}
不同的是,在第二种实现中,function调用自己作为一个goroutine。 (第 go recur(iter-1)
行)
有人可以解释这种行为吗?
如果您将所有内容设为异步,main
中就没有任何内容可以等待。您必须显式地等待 go 例程,以便您的程序不会在递归过程完成之前退出。
使用sync.WaitGroup
or something similar for synchronization. Example (On Play):
func recur(iter int, g *sync.WaitGroup) {
defer g.Done()
if iter <= 0 {
return
}
fmt.Println(iter)
go recur(iter-1, g)
}
func main() {
g := &sync.WaitGroup{}
runs := 5
g.Add(runs)
recur(runs, g)
g.Wait()
}
在所有 goroutine 完成之前,您的程序正在退出。最简单的看这部作品的方法如下
package main
import (
"fmt"
"time"
)
func recur(iter int) {
if iter <= 0 {
return
}
fmt.Println(iter)
go recur(iter - 1)
}
func main() {
recur(5)
time.Sleep(time.Second)
}
但是,您可能希望将 sync.WaitGroup
传递给您的函数,而不是休眠。