
在 Go 程序中捕获 Ctrl+C(SIGINT)时,终端默认会回显 ^C,可通过输出回车符 \r 覆盖该字符,再打印自定义退出信息,从而实现干净的中断体验。
在 Go 程序中捕获 `Ctrl+C`(`SIGINT`)时,终端默认会回显 `^C`,可通过输出回车符 `\r` 覆盖该字符,再打印自定义退出信息,从而实现干净的中断体验。
Go 本身不直接控制终端的输入回显行为——^C 是由终端驱动(terminal driver)在接收到 Ctrl+C 时主动输出的,属于行编辑层(如 icanon 模式下的 echoctl 特性),而非 Go 进程打印的结果。因此,无法通过 signal.Notify 或修改 Go 信号处理逻辑来禁用 ^C 的显示;但可以在信号到达后,立即用 \r 将光标移至行首,并覆盖掉已显示的 ^C。
最简单有效的做法是:在接收到中断信号后,先输出 \r(回车),再输出你的日志或提示信息。由于 \r 不换行,后续文本将从当前行开头开始覆盖,从而“擦除”或掩盖 ^C:
package main
import (
"fmt"
"log"
"os"
"os/signal"
"syscall"
"time"
)
func main() {
// 模拟长时间运行任务
done := make(chan bool)
go func() {
time.Sleep(5 * time.Second)
done <p>⚠️ 注意事项:</p>
- \r 仅对当前行有效;若 ^C 出现在多行日志中间,或终端已滚动,覆盖效果可能不理想;
- 此方法依赖终端支持标准 ANSI 行为(几乎所有现代终端均支持);
- 如需更彻底地禁用 ^C 回显(例如开发交互式 CLI 工具),应使用 golang.org/x/term 或 github.com/mattn/go-tty 等库,在程序启动时调用 term.MakeRaw() 进入原始模式(raw mode),此时终端将不再处理 Ctrl+C 的回显与信号生成,需手动解析字节流并显式发送 SIGINT——但这会显著增加复杂度,通常非必要不推荐;
- 生产环境中建议配合优雅退出(graceful shutdown):在 \r 后给出明确状态反馈,并预留资源释放时间,避免强制 os.Exit(0) 导致数据丢失。
综上,fmt.Print("\r") 是平衡简洁性与可用性的首选方案,适用于绝大多数命令行工具场景。











