You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Golang批量删除文件工具:如何替代time.Sleep处理Ctrl+C中断?

批量删除工具的Ctrl+C中断优化方案

问题描述

我编写了一个批量删除文件的工具,通过inFile指定待删除文件列表,每个文件需手动确认,仅输入空内容时才执行删除操作。目前代码中加入time.Sleep处理Ctrl+C中断:若移除该语句,按下Ctrl+C后stdinScanner.Scan()返回false且无错误,文本为空,导致当前文件被误删;加入sleep可避免此问题,但方案不够优雅。

工具代码如下:

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

替代方案:捕获SIGINT信号并检查中断状态

核心思路是通过Go的os/signal包捕获Ctrl+C触发的SIGINT信号,设置一个中断标志,在执行删除操作的关键节点检查该标志,一旦检测到中断就退出流程,避免误删。

修改后的代码示例

import (
    "bufio"
    "fmt"
    "os"
    "os/signal"
    "strings"
    "syscall"
)

var isInterrupted bool

func init() {
    // 创建信号通道,监听SIGINT(Ctrl+C)
    sigChan := make(chan os.Signal, 1)
    signal.Notify(sigChan, syscall.SIGINT)
    
    // 在goroutine中处理信号,避免阻塞主流程
    go func() {
        <-sigChan
        isInterrupted = true
        fmt.Println("\n收到中断信号,终止操作")
    }()
}

func main() {
    // 假设inFile已提前打开
    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 isInterrupted {
                os.Exit(0)
            }
            
            input := stdinScanner.Text()
            if len(input) > 0 {
                fmt.Println("Non empty return not allowed")
                os.Exit(1)
            } else {
                // 再次检查中断,避免等待输入后到删除前的间隙收到信号
                if isInterrupted {
                    os.Exit(0)
                }
                
                e := os.Remove(target)
                if e != nil {
                    panic(e)
                }
                printUtf16("%s deleted\n", target)
            }
        }
    }
}

关键逻辑说明

  1. 信号捕获:在init函数中启动goroutine监听SIGINT信号,一旦收到就将isInterrupted设为true,并提示用户。
  2. 中断检查:在两个关键节点检查中断状态:
    • 读取用户输入后立即检查,避免用户按下Ctrl+C后直接进入删除流程
    • 执行删除操作前再次检查,覆盖输入完成后到删除前的时间间隙
  3. 无延迟响应:不需要依赖time.Sleep,中断信号会被实时捕获并处理,逻辑更可靠也更优雅。

内容的提问来源于stack exchange,提问作者user1763590

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 15:55:20