我有一个函数调用另一个返回chan数组的函数。我目前有一个for循环遍历数组中的范围,该程序运行程序无限期地输出通道更新。
func getRoutes() {
for r := range rtu {
if r.Type == 24 {
fmt.Printf("Route added: %s via %s\n",r.Dst.String(),r.Gw.String())
} else if r.Type == 25 {
fmt.Printf("Route deleted: %s via %s\n",r.Dst.String(),r.Gw.String())
}
}
}
当我从main()调用getRoutes()时,一切都按计划运行,它阻止了应用程序。我尝试从go getRoutes()
拨打main()
,但似乎根本没有调用该功能。
如何使用go例程以非阻塞方式在后台运行此函数?
答案 0 :(得分:3)
当main
处的主要goroutine退出时,您可能产生的所有goroutine将被孤立并最终死亡。
您可以通过for {}
的无限循环让主goroutine永远运行,但您可能希望保留退出渠道:
exit := make(chan string)
// Spawn all you worker goroutines, and send a message to exit when you're done.
for {
select {
case <- exit: {
os.Exit(0)
}
}
}
更新:CeriseLimón指出,当主要出口时,goroutines会立即被杀死。我认为这应该是官方指定的行为。
答案 1 :(得分:0)
你的main()
在getRoutes()
之前返回 - goroutine结束。当main()
返回时,程序退出,从而杀死所有正在运行的goroutine。 (即使在goroutine有机会通过运行时调度之前,main()
也完全有可能返回。)
如果你想让main()
(或任何其他函数)等待一组goroutine完成,你必须以某种方式明确地等待该函数。有多种方法可以做到这一点。 sync.WaitGroup.Wait()
可用于等待一组goroutine完成。你也可以在完成goroutine时使用频道进行交流。
答案 2 :(得分:0)
尽管其他人已经回答了这个问题,但我认为他们的解决方案在某些情况下可以简化。
使用以下代码段:
func main() {
go doSomething()
fmt.Println("Done.")
}
func doSomething() {
for i := 0; i < 10; i++ {
fmt.Println("Doing something...")
time.Sleep(time.Second)
}
}
main()
开始执行时,它会产生一个线程来同时执行doSomething()
。然后,它立即执行fmt.Println("Done.")
,然后完成main()
。
main()
完成后,所有其他goroutine将被孤立并死亡。
为避免这种情况,我们可以在main()
的末尾放置一个阻塞操作,以等待goroutine的输入。通过渠道最简单的方法是
var exit = make(chan bool)
func main() {
go doSomething()
<-exit // This blocks until the exit channel receives some input
fmt.Println("Done.")
}
func doSomething() {
for i := 0; i < 10; i++ {
fmt.Println("Doing something...")
time.Sleep(time.Second)
}
exit<-true // Notify main() that this goroutine has finished
}