英文:
recursive function in go language
问题
我几天前开始学习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
。当我在调用recv
之前删除go
关键字时,打印出10
到0
。我相信我在这里错误地使用了Go协程,但我不明白为什么以这种方式启动一个Go协程会失败。
英文:
I started to learn go language days ago. When I tried to start writing some fun codes, I am stuck by a strange behavior.
package main
import "fmt"
func recv(value int) {
if value < 0 {
return
}
fmt.Println(value)
go recv(value-1)
}
func main() {
recv(10)
}
when I run the above code, only 10
is printed. When I remove the go
before the call to recv
, 10
to 0
are printed out. I believe I am misusing go routine here, but I can not understand why it failed start a go routine this way.
答案1
得分: 16
当主函数返回时,Go语言不会等待任何仍然存在的goroutine完成,而是直接退出。
recv
函数在第一次“迭代”后将返回到主函数,因为主函数没有其他任务要执行,程序将终止。
解决这个问题的一种方法是使用一个信号通道来表示所有工作都已完成,如下所示:
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
函数会在通道上等待该消息。
对于程序的逻辑来说,使用的类型或具体值并不重要。bool
和true
只是一个简单的示例。如果想要更高效,可以使用chan struct{}
而不是chan bool
,这样可以节省一个额外的字节,因为空结构体不使用任何内存。
英文:
When the main function returns, Go will not wait for any still existing goroutines to finish but instead just exit.
recv
will return to main after the first "iteration" and because main has nothing more to do, the program will terminate.
One solution to this problem is to have a channel that signals that all work is done, like the following:
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
}
Here, recv
will send a single boolean before returning, and main
will wait for that message on the channel.
For the logic of the program, it does not matter what type or specific value you use. bool
and true
are just a straightforward example. If you want to be more efficient, using a chan struct{}
instead of a chan bool
will save you an additional byte, since empty structs do not use any memory.
答案2
得分: 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) // 将1个goroutine添加到waitgroup中。
go func() {
recv(value-1, wg)
wg.Done() // 这个goroutine已经完成。
}()
}
func main() {
var wg sync.WaitGroup
recv(10, &wg)
// 阻塞直到waitgroup发出信号
// 所有的goroutine都已经完成。
wg.Wait()
}
英文:
A sync.Waitgroup
is another solution and specifically intended for the purpose of waiting for an arbitrary amount of goroutines to run their course.
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()
}
答案3
得分: -2
我这样做了,也起作用。为什么?
package main
import "fmt"
func recv(value int) {
if value < 0 {
return
}
fmt.Println(value)
recv(value - 1)
}
func main() {
recv(10)
}
英文:
I did so and also worked. How come?
package main
import "fmt"
func recv(value int) {
if value < 0 {
return
}
fmt.Println(value)
recv(value - 1)
}
func main() {
recv(10)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论