英文:
How to end a go program from a goroutine
问题
我正在尝试在使用Go编写的命令行界面中实现一些非典型的行为。
我有一个长时间运行的函数,并且我希望在某人通过ctrl-c退出该函数时运行一个清理函数。
以下是代码的示例:
func longRunningFunction() {
//一些设置
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
go func() {
<-sigs
fmt.Println("收到中断信号")
cleanup()
}()
//长时间运行的命令
fmt.Println("结束")
}
在正常情况下,不需要使用ctrl-c,函数将正常完成。(因此,我不能在主线程中有一个(如通道)阻塞,直到清理goroutine完成。)然而,在用户按下ctrl-c的情况下,我希望立即结束程序,而不打印"结束"(最好也不完成长时间运行的命令)。
但目前情况并非如此。当前的命令行输出如下所示:
...
//长时间运行命令的输出
^C收到中断信号
//清理代码的输出
$
//更多长时间运行命令的输出
结束
我对几个问题感到困惑 - 为什么程序在提示符返回后仍然打印输出,为什么仍然打印"结束"?我如何避免这种行为?在Go中是否可能出现这种情况?谢谢!
英文:
I'm trying to implement some non-typical behavior in a command line interface written in go.
I have a function that runs for a long time, and I want to have a cleanup function that runs when someone ctrl-c's out of that function.
Here's a mock-up of the code:
func longRunningFunction() {
//some set up stuff
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
go func() {
<-sigs
fmt.Println("Got an interrupt")
cleanup()
}()
//the long-running command
fmt.Println("the end")
}
In the normal case, using ctrl-c will not be necessary and the function will finish normally. (Because of this, I can't have something (like a channel) in the main thread that blocks until the cleanup goroutine has finished.) However, in the case that a user does press ctrl-c, I would like to end the program immediately, not printing "the end" (and ideally not finishing the long-running command).
That's not happening right now. Currently, the command line output looks like this:
...
//long-running-command's output
^CGot an interrupt
//cleanup code's output
$
//more of long-running-command's output
the end
I'm confused on a few fronts - why is the program still printing after the prompt returns, and why is "the end" still being printed? How can I avoid this behavior? Is this scenario even possible in go? Thanks!
答案1
得分: 3
你正在信号处理程序之后继续执行。如果你想退出进程,请调用os.Exit
函数:
go func() {
<-sigs
fmt.Println("收到中断信号")
cleanup()
os.Exit(2)
}()
英文:
You're continuing execution after your signal handler. If you want to exit the process, call os.Exit
:
go func() {
<-sigs
fmt.Println("Got an interrupt")
cleanup()
os.Exit(2)
}()
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论