我有一个函数调用另一个返回 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())
}
}
}
Run Code Online (Sandbox Code Playgroud)
当我从 main() 调用 getRoutes() 时,一切都按计划进行,但它阻塞了应用程序。我试过调用go getRoutes()frommain()虽然它看起来好像根本没有调用该函数。
如何使用 go 例程以非阻塞方式在后台运行此函数?
当主协程main退出时,您可能产生的所有协程都将成为孤儿并最终死亡。
您可以使用 无限循环使主 goroutine 永远运行for {},但您可能希望保留一个退出通道:
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)
}
}
Run Code Online (Sandbox Code Playgroud)
更新: Cerise Limón 指出 goroutines 在 main 退出时会立即被杀死。我认为这应该是官方指定的行为。
另一个更新:当您有多种退出方式/多个退出渠道时,for-select 效果更好。对于单个退出渠道,您可以这样做
<-exit
Run Code Online (Sandbox Code Playgroud)
在最后而不是一个for和select循环。
尽管其他人已经回答了这个问题,但我认为他们的解决方案在某些情况下可以简化。
采取这个代码片段:
func main() {
go doSomething()
fmt.Println("Done.")
}
func doSomething() {
for i := 0; i < 10; i++ {
fmt.Println("Doing something...")
time.Sleep(time.Second)
}
}
Run Code Online (Sandbox Code Playgroud)
当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
}
Run Code Online (Sandbox Code Playgroud)