【问题标题】:How to end a go program from a goroutine如何从 goroutine 结束 go 程序
【发布时间】:2017-08-06 17:32:12
【问题描述】:

我正在尝试在用 go 编写的命令行界面中实现一些非典型行为。

我有一个可以运行很长时间的函数,我想要一个清理函数,当有人 ctrl-c 退出该函数时运行。

这是代码的模型:

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")
}

在正常情况下,不需要使用 ctrl-c 并且该功能将正常完成。 (因此,在清理 goroutine 完成之前,我不能在主线程中有阻塞的东西(比如通道)。)但是,如果用户确实按下 ctrl-c,我想结束立即编程,不打印“结束”(理想情况下不完成长时间运行的命令)。

现在还没有发生。目前,命令行输出如下所示:

...
//long-running-command's output
^CGot an interrupt
//cleanup code's output
$
//more of long-running-command's output
the end

我在几个方面感到困惑 - 为什么在提示返回后程序仍在打印,为什么仍在打印“结束”?我怎样才能避免这种行为?这种情况甚至可能在go中出现吗?谢谢!

【问题讨论】:

    标签: go command-line-interface channel goroutine


    【解决方案1】:

    您在信号处理程序之后继续执行。如果要退出进程,请拨打os.Exit

    go func() {
        <-sigs
        fmt.Println("Got an interrupt")
        cleanup()
        os.Exit(2)
    }()
    

    【讨论】:

    • 感谢您的快速回复!但这不只是结束 goroutine 吗?我之前尝试过,我得到了相同的命令行输出。
    • @LizFurlan:来自文档:The program terminates immediately;。在那之后没有其他东西会运行。
    • 哦,我现在看到了问题。 os.Exit(2) 确实有效(谢谢!)但直到其他所有内容都被执行后才会发生(即打印“结束”) - 你知道是否有办法我可以强制 cleanup()os.Exit(2)一起发生吗?
    • @LizFurlan:在这种情况下,“一起”是什么意思?要么你已经退出,要么你还没有。你可以从cleanup 调用os.Exit,但如果它是最后一个调用它不会有任何区别。 longRunningFunction 只是在调用 os.Exit 之前到达“结束”,如果你不希望这种情况发生,你需要自己阻止它。
    • 对不起,我不清楚。 “在一起”意味着os.Exit(2) 是在cleanup() 之后发生的第一件事(而不是fmt.Println("the end") 在它们之间执行)
    猜你喜欢
    • 2018-07-01
    • 2013-08-06
    • 2017-01-22
    • 1970-01-01
    • 2018-03-26
    • 2021-09-08
    • 2014-11-03
    • 2015-03-02
    • 2020-07-22
    相关资源
    最近更新 更多