Nat*_*ate 41 daemon go goroutine
我用Go编写了一个长期运行的服务器.Main触发了程序逻辑执行的几个goroutine.之后主要没有任何用处.一旦主要退出,程序将退出.我现在用来保持程序运行的方法只是对fmt.Scanln()的简单调用.我想知道别人如何保持主力退出.以下是一个基本的例子.这里可以使用哪些想法或最佳实践?
我考虑通过在所述频道上接收来创建一个频道并延迟主要的退出,但我认为如果我的所有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)
}
}
Run Code Online (Sandbox Code Playgroud)
pet*_*rSO 55
永远阻止.例如,
package main
import (
"fmt"
"time"
)
func main() {
go forever()
select {} // block forever
}
func forever() {
for {
fmt.Printf("%v+\n", time.Now())
time.Sleep(time.Second)
}
}
Run Code Online (Sandbox Code Playgroud)
小智 27
Go的运行时的当前设计假定程序员负责检测何时终止goroutine以及何时终止程序.程序员需要计算goroutines以及整个程序的终止条件.程序可以通过调用os.Exit或从main()函数返回以正常方式终止.
main()通过立即接收所述频道来创建频道并延迟退出是防止main退出的有效方法.但它没有解决检测何时终止程序的问题.
如果在main()函数进入wait-for-all-goroutines-to-terminate循环之前无法计算goroutine的数量,则需要发送增量,以便该main函数可以跟踪正在运行的goroutine的数量:
// Receives the change in the number of goroutines
var goroutineDelta = make(chan int)
func main() {
go forever()
numGoroutines := 0
for diff := range goroutineDelta {
numGoroutines += diff
if numGoroutines == 0 { os.Exit(0) }
}
}
// Conceptual code
func forever() {
for {
if needToCreateANewGoroutine {
// Make sure to do this before "go f()", not within f()
goroutineDelta <- +1
go f()
}
}
}
func f() {
// When the termination condition for this goroutine is detected, do:
goroutineDelta <- -1
}
Run Code Online (Sandbox Code Playgroud)
另一种方法是用通道替换通道sync.WaitGroup.这种方法的一个缺点是wg.Add(int)需要在调用之前调用wg.Wait(),因此有必要创建至少1个goroutine in,main()而后续的goroutine可以在程序的任何部分创建:
var wg sync.WaitGroup
func main() {
// Create at least 1 goroutine
wg.Add(1)
go f()
go forever()
wg.Wait()
}
// Conceptual code
func forever() {
for {
if needToCreateANewGoroutine {
wg.Add(1)
go f()
}
}
}
func f() {
// When the termination condition for this goroutine is detected, do:
wg.Done()
}
Run Code Online (Sandbox Code Playgroud)
jma*_*ney 17
Go的运行时包有一个名为的函数runtime.Goexit,可以完全按照你的意愿执行.
从主goroutine调用Goexit会终止那个没有func main返回的goroutine.由于func main尚未返回,程序继续执行其他goroutine.如果所有其他goroutine退出,程序崩溃.
在操场上的例子
package main
import (
"fmt"
"runtime"
"time"
)
func main() {
go func() {
time.Sleep(time.Second)
fmt.Println("Go 1")
}()
go func() {
time.Sleep(time.Second * 2)
fmt.Println("Go 2")
}()
runtime.Goexit()
fmt.Println("Exit")
}
Run Code Online (Sandbox Code Playgroud)
jas*_*siu 10
没有人提到 signal.Notify(c chan<- os.Signal, sig ...os.Signal)
例子:
package main
import (
"fmt"
"time"
"os"
"os/signal"
"syscall"
)
func main() {
go forever()
quitChannel := make(chan os.Signal, 1)
signal.Notify(quitChannel, syscall.SIGINT, syscall.SIGTERM)
<-quitChannel
//time for cleanup before exit
fmt.Println("Adios!")
}
func forever() {
for {
fmt.Printf("%v+\n", time.Now())
time.Sleep(time.Second)
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个永远使用通道的简单块
package main
import (
"fmt"
"time"
)
func main() {
done := make(chan bool)
go forever()
<-done // Block forever
}
func forever() {
for {
fmt.Printf("%v+\n", time.Now())
time.Sleep(time.Second)
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
24800 次 |
| 最近记录: |