使用信号

时间:2018-02-06 23:15:27

标签: loops for-loop go signals sigint

我试图制作一个使用信号来中断无限计数器循环的程序。我已设法用SIGINT(ctrl + C)中断程序,但我无法中断它。我想知道我是否可以通过其他方式中断循环,例如在终端中运行时按Q键。

我制作了两个Go文件,第一个包含实际的无限循环:

package infinite

import "fmt"
import "time"

func Infinite01 (msg string) {
for i := 0; ; i++ {
    fmt.Println(msg, i)
    time.Sleep(time.Second)
    }
}

然后该文件捕获SIGINT信号并中断循环:

package main

import (
"./infinite"
"os/signal"
"os"
"fmt"
)

func main() {
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, os.Interrupt)
go func() {
    <-sigs
    fmt.Printf("You pressed ctrl + C. User interrupted infinite loop.")
    os.Exit(0)
}()
Loop()
}

func Loop() {
infinite.Infinite01("Look, I can count forever:")
}

1 个答案:

答案 0 :(得分:0)

然后我会坚持我的第一个评论。我会解释一下。

您不需要信号让您的程序终止 - 您可以控制它。随时调用os.Exit将退出该程序,从main()返回具有相同的效果。

问题是,何时触发这些&#34;退出&#34;。或者,在您的示例中,如何在按下key Q时触发退出。

要解决此问题,您需要将其分解为多个部分。正如我在评论中所说,第1部分正在捕捉关键击球。它不像fmt.Scan那么简单,因为它需要用户按下后输入。它需要一些特定于操作系统的代码来执行此操作,但希望lib可以为您节省所有麻烦,例如termbox-go

第2部分与第1部分紧密相关。即指定事件,键击。在您的示例中,要知道按下的键是Q,然后调用os.Exit。通常lib可以很容易地处理它,有时很难注意到有一部分。但是如果你想要一些更复杂的关键词,比如ctrl-alt-backspace,甚至a-s-d-f(同时),这将需要一些代码。

第三部分是关于不阻止该程序。在Go中,可以通过使用单独的goroutine来检查事件循环或使用旧的回调方式轻松实现。这取决于您选择的图书馆。

关于信号和ctrl-c案例的更多信息。通常的做法是ctrl-c必然会在大多数情况下向程序发送一个sigint。如果没有修改,sigint会终止程序。但是,程序可以修改处理sigint的行为,就像你的orignal代码那样(添加一条消息来打印)。当按下其他键时,操作系统不太可能将其绑定到另一个信号,因此您无法处理它。

另一个解决方案是将一个键组合(多个键击)绑定到向程序发送一个sigint,但只要该程序是接收键击本身的程序,那就是一个不情愿的。

注意:由于库的选择可以变化,因此代码差别很大,所以我认为我不能(或应该)提供一个例子。