在Go语言中使用gohook监听键盘事件的同时执行循环任务的实现方案
在Go语言中使用gohook监听键盘事件的同时执行循环任务的实现方案
嘿,我完全懂你的困扰!之前用gohook的示例代码时,监听键盘的操作会把整个程序卡住,没法同时跑其他任务——这其实就是没用到Go的协程(goroutine)而已,咱们调整一下就能解决~
gohook的hook.Start()方法是阻塞式的,它会一直占用当前goroutine来监听事件。所以咱们只需要把监听逻辑放到一个单独的goroutine里,这样主goroutine(或者另一个协程)就能同时执行你的循环任务了。另外,咱们还得加个退出机制,不然程序没法优雅停止,比如监听某个特定按键(比如Esc)来触发退出,同时终止循环任务。
下面是完整的实现代码:
package main import ( "fmt" "os" "time" hook "github.com/robotn/gohook" ) func main() { // 创建一个通道,用来传递退出信号 exitChan := make(chan struct{}) // 启动一个goroutine来监听键盘事件 go func() { // 注册键盘事件监听,这里可以改成你需要的特定按键 evChan := hook.Start() defer hook.End() // 确保退出时清理hook资源 for ev := range evChan { // 检测是否按下Esc键(键码是27),触发退出 if ev.Kind == hook.KeyDown && ev.Keychar == 27 { fmt.Println("\n收到退出信号,正在停止程序...") close(exitChan) return } // 这里可以处理你需要监听的特定按键逻辑 if ev.Kind == hook.KeyDown { fmt.Printf("按下了按键: %c (键码: %d)\n", ev.Keychar, ev.Keycode) } } }() // 主goroutine执行循环任务 fmt.Println("循环任务开始运行,按Esc键退出...") loop: for { select { case <-exitChan: break loop // 收到退出信号,终止循环 default: // 这里写你的循环任务逻辑,比如打印当前时间 fmt.Printf("当前时间: %s\n", time.Now().Format("2006-01-02 15:04:05")) time.Sleep(1 * time.Second) // 模拟任务耗时 } } fmt.Println("程序已退出") }
代码关键点说明:
- 用
go func() {...}()把监听逻辑包装成一个协程,这样它就不会阻塞主程序的执行了。 exitChan是一个无缓冲通道,用来在监听协程和主协程之间传递退出信号,确保两者能同步停止。select语句让循环任务既能持续执行,又能随时响应退出信号,不会一直卡在循环里没法停止。defer hook.End()很重要,它会在监听协程退出时自动清理gohook的资源,避免内存泄漏。
小提示:
如果你需要监听多个特定按键,只需要在for ev := range evChan的循环里增加对应的判断条件就行。另外,如果你的循环任务涉及到共享资源,记得用sync.Mutex来做并发安全保护,避免出现竞态问题。
内容来源于stack exchange
相关产品推荐
相关产品推荐

