为了账号安全,请及时绑定邮箱和手机立即绑定

如何在不进入 Golang 循环的情况下捕获按键

如何在不进入 Golang 循环的情况下捕获按键

Go
holdtom 2023-06-05 09:46:59
我有一个循环,其中一些事情根据它运行的状态(手动/自动/学习)发生。我现在希望能够通过按键盘上的伴随字母(“m”代表手动,“a”代表自动,“l”代表学习)让程序在这些状态之间切换。所以要做到这一点,我需要能够在循环期间捕捉到按键并相应地更改变量状态。我现在有以下内容,它可以捕捉到一个按键,然后是一个输入:ch := make(chan string)go func(ch chan string) {    reader := bufio.NewReader(os.Stdin)    for {        s, _ := reader.ReadString('\n')        ch <- s    }}(ch)for {    select {        case stdin, _ := <-ch:            fmt.Println("Keys pressed:", stdin)        default:            fmt.Println("Working..")    }    time.Sleep(time.Second)}但我需要按下回车键这一事实是不可接受的。有没有人知道一种非阻塞的方式来捕获普通字母(不是 SIGINT)的按键而无需事后按回车键?
查看完整描述

3 回答

?
一只斗牛犬

TA贡献1784条经验 获得超2个赞

在阅读 os.Stdin.Read() 并找到这个答案后,我创建了以下代码:


package main


import (

    "fmt"

    "os"

    "time"

    "os/exec"

)


func main() {

    ch := make(chan string)

    go func(ch chan string) {

        // disable input buffering

        exec.Command("stty", "-F", "/dev/tty", "cbreak", "min", "1").Run()

        // do not display entered characters on the screen

        exec.Command("stty", "-F", "/dev/tty", "-echo").Run()

        var b []byte = make([]byte, 1)

        for {

            os.Stdin.Read(b)

            ch <- string(b)

        }

    }(ch)


    for {

        select {

            case stdin, _ := <-ch:

                fmt.Println("Keys pressed:", stdin)

            default:

                fmt.Println("Working..")

        }

        time.Sleep(time.Millisecond * 100)

    }

}

这就像一个魅力。


查看完整回答
反对 回复 2023-06-05
?
跃然一笑

TA贡献1826条经验 获得超6个赞

因为你正在使用ReadStringwhich 期望你给它的任何参数,在你的情况下 - 关键return。根据文档:

ReadString 一直读取到输入中第一次出现 delim,返回一个包含数据的字符串,直到并包括分隔符。

这意味着在您按下该键之前,该方法不会返回return

您可以改用常规的Read方法来读取您需要的字符。


查看完整回答
反对 回复 2023-06-05
?
江户川乱折腾

TA贡献1851条经验 获得超5个赞

如果你想检查是否按下了某个键而不阻塞它所在的进程,你应该使用这样的东西:


import (

   ...

   "golang.org/x/sys/windows"

)


var user32_dll  = windows.NewLazyDLL("user32.dll")

var GetKeyState = user32_dll.NewProc("GetKeyState")


func wasESCKeyPressed() bool {

    r1, _, _ := GetKeyState.Call(27) // Call API to get ESC key state.

    return r1 == 65409               // Code for KEY_UP event of ESC key.

}


func loop() {

    for {

       // Do something...

       if wasESCKeyPressed() {

           break

       }

       // Do something...

       time.Sleep(time.Millisecond * 10)

    }

}


查看完整回答
反对 回复 2023-06-05
  • 3 回答
  • 0 关注
  • 140 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信