如何在不进入 Golang 循环的情况下捕获按键
How to catch keypress without enter in Golang loop
我有一个循环,其中一些事情根据它运行的状态发生 (manual/automatic/learning)。我现在希望能够通过按键盘上的伴随字母("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)的按键而不需要之后按回车键?
因为您使用的是 ReadString
,它需要您提供的任何参数,在您的情况下 - return
键。
根据the docs:
ReadString reads until the first occurrence of delim in the input,
returning a string containing the data up to and including the
delimiter.
这意味着在您按下 return
键之前,该方法不会 return。
您可以改用常规的 Read 方法来读取您需要的字符。
另请参阅此 Whosebug question 以供参考。
阅读 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)
}
}
这很有魅力。
我有一个循环,其中一些事情根据它运行的状态发生 (manual/automatic/learning)。我现在希望能够通过按键盘上的伴随字母("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)的按键而不需要之后按回车键?
因为您使用的是 ReadString
,它需要您提供的任何参数,在您的情况下 - return
键。
根据the docs:
ReadString reads until the first occurrence of delim in the input, returning a string containing the data up to and including the delimiter.
这意味着在您按下 return
键之前,该方法不会 return。
您可以改用常规的 Read 方法来读取您需要的字符。 另请参阅此 Whosebug question 以供参考。
阅读 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)
}
}
这很有魅力。