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

标签 go concurrency stdin keypress nonblocking

我有一个循环,其中一些事情根据它运行的状态(手动/自动/学习)发生。我现在希望能够通过按键盘上的伴随字母(“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)
}

但我需要按下回车键这一事实是 Not Acceptable 。

有没有人知道一种非阻塞的方式来捕获普通字母(不是 SIGINT)的按键而不需要之后按回车键?

最佳答案

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

这就像一个魅力。

关于go - 如何在不进入 Golang 循环的情况下捕获按键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54422309/

相关文章:

ajax - 在返回之前如何合并两个 gorountines 的结果?

go - 在复制 slice 并使用副本后更改 slice

perl - 我认为在 perl 中的 Telnet 输入缓冲区问题

golang 从 stdin 读取长文本

go - 使用 Go Micro 从一个经纪人消费并生产到另一个经纪人

Golang (cgo) - 任意 void* 接口(interface)

python - 在 Python 中发送 100,000 个 HTTP 请求的最快方法是什么?

java - 多个 Swing 工作器,用于具有各种按钮的应用

java - 在这种情况下如何实现线程?

delphi - 在 Delphi 控制台应用程序中的 stdin/stdout 上打开 TStream