如何最好地保持长时间运行的Go程序的运行?

我有一个用Go语言编写的运行时间较长的服务器。Main会触发执行程序逻辑的多个goroutine。在那之后主要没有任何用处。一旦主程序退出,程序将退出。我现在使用的使程序运行的方法只是对fmt.Scanln()的简单调用。我想知道其他人如何阻止main退出。以下是一个基本示例。在这里可以使用哪些想法或最佳做法?


我考虑过创建一个通道并通过接收该通道来延迟main的退出,但是我认为如果我的所有goroutine在某个时候都变得不活动,那可能会出现问题。


旁注:在我的服务器(不是示例)中,该程序实际上并没有连接到Shell上运行,因此无论如何与控制台进行交互都没有任何意义。目前它可以工作,但是我正在寻找“正确”的方法,假设有一种方法。


package main


import (

    "fmt"

    "time"

)


func main() {

    go forever()

    //Keep this goroutine from exiting

    //so that the program doesn't end.

    //This is the focus of my question.

    fmt.Scanln()

}


func forever() {

    for ; ; {

    //An example goroutine that might run

    //indefinitely. In actual implementation

    //it might block on a chanel receive instead

    //of time.Sleep for example.

        fmt.Printf("%v+\n", time.Now())

        time.Sleep(time.Second)

    }

}


哔哔one
浏览 377回答 3
3回答

LEATH

Go的当前运行时设计假定程序员负责检测何时终止goroutine和何时终止程序。程序员需要计算goroutine以及整个程序的终止条件。可以通过调用os.Exit或从main()函数返回以正常方式终止程序。main()通过立即在所述通道上接收来创建通道并延迟退出,是一种防止main退出的有效方法。但是它不能解决检测何时终止程序的问题。如果在main()函数进入等待所有goroutines终止循环之前无法计算goroutine的数量,则需要发送增量,以便main函数可以跟踪正在运行的goroutine的数量:// Receives the change in the number of goroutinesvar goroutineDelta = make(chan int)func main() {&nbsp; &nbsp; go forever()&nbsp; &nbsp; numGoroutines := 0&nbsp; &nbsp; for diff := range goroutineDelta {&nbsp; &nbsp; &nbsp; &nbsp; numGoroutines += diff&nbsp; &nbsp; &nbsp; &nbsp; if numGoroutines == 0 { os.Exit(0) }&nbsp; &nbsp; }}// Conceptual codefunc forever() {&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; if needToCreateANewGoroutine {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Make sure to do this before "go f()", not within f()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; goroutineDelta <- +1&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; go f()&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}func f() {&nbsp; &nbsp; // When the termination condition for this goroutine is detected, do:&nbsp; &nbsp; goroutineDelta <- -1}另一种方法是将频道替换为sync.WaitGroup。这种方法的缺点是wg.Add(int)需要在调用之前先进行调用wg.Wait(),因此必须在其中至少创建一个goroutine,main()然后才能在程序的任何部分中创建后续goroutine:var wg sync.WaitGroupfunc main() {&nbsp; &nbsp; // Create at least 1 goroutine&nbsp; &nbsp; wg.Add(1)&nbsp; &nbsp; go f()&nbsp; &nbsp; go forever()&nbsp; &nbsp; wg.Wait()}// Conceptual codefunc forever() {&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; if needToCreateANewGoroutine {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; wg.Add(1)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; go f()&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}func f() {&nbsp; &nbsp; // When the termination condition for this goroutine is detected, do:&nbsp; &nbsp; wg.Done()}

jeck猫

Go的运行时程序包具有一个名为的函数runtime.Goexit,该函数可以完全满足您的要求。从主goroutine调用Goexit会终止该goroutine,而不会返回func main。由于func main尚未返回,因此程序将继续执行其他goroutine。如果所有其他goroutine退出,程序将崩溃。在操场上的例子package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "runtime"&nbsp; &nbsp; "time")func main() {&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; time.Sleep(time.Second)&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("Go 1")&nbsp; &nbsp; }()&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; time.Sleep(time.Second * 2)&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("Go 2")&nbsp; &nbsp; }()&nbsp; &nbsp; runtime.Goexit()&nbsp; &nbsp; fmt.Println("Exit")}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go