【问题标题】:How to catch keypress without enter in Golang loop如何在不进入 Golang 循环的情况下捕获按键
【发布时间】:2019-06-22 15:43:04
【问题描述】:

我有一个循环,其中根据运行状态(手动/自动/学习)发生一些事情。我现在希望能够通过按键盘上的随附字母让程序在这些状态之间切换(“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)的按键而无需在之后按 Enter 键?

【问题讨论】:

  • 您可以只使用os.Stdin.Read() 来从线路中读取字节。您的代码明确地包装它并绕过它,以便在用户下次按下回车时进行缓冲。

标签: go concurrency stdin keypress nonblocking


【解决方案1】:

因为您使用的是ReadString,它需要您提供的任何参数,在您的情况下 - return 键。 根据the docs

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

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

您可以改用常规的Read 方法来读取您需要的字符。 另请参阅此Stackoverflow question 以供参考。

【讨论】:

    【解决方案2】:

    在阅读了有关 os.Stdin.Read() 并找到 this answer 之后,我创建了以下代码:

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

    这就像一个魅力。

    【讨论】:

    • 取决于外部实用程序,肯定不能在 Windows 上运行。但是感谢您的代码。
    猜你喜欢
    • 1970-01-01
    • 2015-12-01
    • 1970-01-01
    • 2021-03-27
    • 1970-01-01
    • 2011-07-14
    • 2012-02-05
    • 2013-01-03
    • 1970-01-01
    相关资源
    最近更新 更多