英文:
Golang detect system interrupt
问题
我写了一个批量删除文件的实用程序,代码如下:
stdinScanner := bufio.NewScanner(os.Stdin)
fileScanner := bufio.NewScanner(inFile)
for fileScanner.Scan() {
target := strings.TrimSpace(fileScanner.Text())
if len(target) > 0 {
printUtf16("Delete %s?\n", target)
stdinScanner.Scan()
if len(stdinScanner.Text()) > 0 {
fmt.Println("Non empty return not allowed")
os.Exit(1)
} else {
// TROUBLE: Had to sleep here or interrupt does not work
time.Sleep(100 * time.Millisecond)
e := os.Remove(target)
if e != nil {
panic(e)
}
printUtf16("%s deleted\n", target)
}
}
}
我有一个名为 inFile 的文件,其中列出了我想要删除的文件列表。对于每个要删除的文件,我会提示自己以确保操作正确。只有当我输入空输出时,程序才会删除文件并继续处理下一个文件。
现在请注意代码中非常丑陋的 time.Sleep。我注意到,如果我没有插入这个 time.Sleep,当我按下 ctrl+c 时,应用程序的行为会出现意外情况。似乎在按下 ctrl+c 后,stdinScanner.Scan() 会返回 false,没有错误,并且 stdinScanner.Text() 会为空,就像我在输入空内容时所期望的那样。在应用程序被中断并退出之前,我被提示的文件将被删除。
我注意到添加这个 time.Sleep 可以让应用程序有足够的时间退出,并防止当前文件被删除。然而,我真的不喜欢这个解决方案。我想知道是否有一个函数可以调用,而不是使用 time.Sleep,来检查应用程序当前是否正在处理键盘中断,如果是的话,我们就不删除当前文件。
英文:
I wrote an utility to batch delete files as followed
stdinScanner := bufio.NewScanner(os.Stdin)
fileScanner := bufio.NewScanner(inFile)
for fileScanner.Scan() {
target := strings.TrimSpace(fileScanner.Text())
if len(target) > 0 {
printUtf16("Delete %s?\n", target)
stdinScanner.Scan()
if len(stdinScanner.Text()) > 0 {
fmt.Println("Non empty return not allowed")
os.Exit(1)
} else {
// TROUBLE: Had to sleep here or interrupt does not work
time.Sleep(100 * time.Millisecond)
e := os.Remove(target)
if e != nil {
panic(e)
}
printUtf16("%s deleted\n", target)
}
}
}
I have an inFile that specifies a list of files I want to delete. For every file to delete, I prompt myself just to be sure. Only if I enter empty output would the program delete the file and proceed to the next file.
Now note the very ugly time.Sleep in this middle of the code. I have noticed that if I did not insert that time.Sleep the application behaves unexpectedly when I press ctrl+c. Seems like after ctrl+c is pressed stdinScanner.Scan() would return false and no error and stdinScanner.Text() would be empty just as I expected when an empty input is entered. The file that I was prompted for would be deleted before the application is interrupted and quits.
I have noticed that adding this time.Sleep allows the application more than sufficient time to exit and prevent the current file to be deleted. However I really dislike this solution. Just asking if there is a function I can call instead of the time.Sleep to check if the application is currently processing a keyboard interrupt and if so we don't delete the current file?
答案1
得分: 0
感谢Volker和Cerise的回复
答案其实很简单。真不敢相信我竟然忽略了它。我们只需要在继续之前检查扫描器的返回值和错误。
scanResult := stdinScanner.Scan()
scanError := stdinScanner.Err()
if scanResult && scanError == nil {
if len(stdinScanner.Text()) > 0 {
fmt.Println("不允许返回非空值")
os.Exit(1)
} else {
deleteFunc(target)
}
} else {
errString := "无"
if scanError != nil {
errString = scanError.Error()
}
fmt.Printf("扫描器返回值为 %t,错误信息:%s\n", scanResult, errString)
os.Exit(1)
}
英文:
Thanks Volker and Cerise for the response
The answer turns out is quite simple. Can't believe I overlooked it. We just need to check scanner's return and err before proceeding
scanResult := stdinScanner.Scan()
scanError := stdinScanner.Err()
if scanResult && scanError == nil {
if len(stdinScanner.Text()) > 0 {
fmt.Println("Non empty return not allowed")
os.Exit(1)
} else {
deleteFunc(target)
}
} else {
errString := "None"
if scanError != nil {
errString = scanError.Error()
}
fmt.Printf("Scanner returns %t, err: %s\n", scanResult, errString)
os.Exit(1)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论