无限期地运行Go例程

时间:2017-01-04 03:22:58

标签: go

我有一个函数调用另一个返回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例程以非阻塞方式在后台运行此函数?

3 个答案:

答案 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
}