在Go语言中从标准输入读取一个字符(无需按下Enter键)

37

我希望我的应用程序显示:

press any key to exit ...

当我按下任意键时退出。

我该如何实现这个功能?

注意:我已经搜索过了,但是所有我找到的方法都需要在结尾按下Enter键。我想要类似于C#中的Console.ReadKey()的功能。

我正在运行MS Windows操作系统。


3
可能是与 Golang中类似于getchar的函数 相关的重复问题。 - zzzz
3
不; 这不是重复的问题。我之前看到过那个问题,并且使用答案中提供的代码仍然需要在标准输入上按回车键。 - Kaveh Shahbazian
重复性仅涉及问题本身,而不涉及任何答案。 - zzzz
7个回答

36

这是一个针对运行UNIX系统的人的最小工作示例:

package main

import (
    "fmt"
    "os"
    "os/exec"
)

func main() {
    // 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)
        fmt.Println("I got the byte", b, "("+string(b)+")")
    }
}

1
你如何将输入的字符显示在屏幕上? - Ibolit
1
Ibolit: 它们已经在示例中显示出来了。要仅显示字符,fmt.Print(string(b)) 应该可以工作。 - blinry
lbolit:使用exec.Command("stty", "-F", "/dev/tty", "echo").Run()命令将它们恢复。 - Joseph Van Riper

15
termbox-go 是一个轻量级的 Go 本地包,提供了一些基本的终端控制功能。包括以原始模式获取输入(一次读取一个字符,而不是默认的行缓冲行为)。
它在不同系统上也有相当好的兼容性。 keyboard 扩展了 termbox-go,提供了一些额外的键盘功能,如多键快捷键和序列。

2
这不是 raw_mode 的定义。 - Awn

11

包"golang.org/x/term"允许您将标准输入(stdin)切换到原始模式(raw mode),以逐个字节地读取。

package main

import (
    "fmt"
    "os"

    "golang.org/x/term"
)

func main() {
    // switch stdin into 'raw' mode
    oldState, err := term.MakeRaw(int(os.Stdin.Fd()))
    if err != nil {
        fmt.Println(err)
        return
    }
    defer term.Restore(int(os.Stdin.Fd()), oldState)

    b := make([]byte, 1)
    _, err = os.Stdin.Read(b)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Printf("the char %q was hit", string(b[0]))
}

10
你可以使用这个库(我的):https://github.com/eiannone/keyboard 以下是获取单个按键的示例:
char, _, err := keyboard.GetSingleKey()
if (err != nil) {
    panic(err)
}
fmt.Printf("You pressed: %q\r\n", char)

伟大的库。至少对于Windows来说,这个解决方案比其他方案更好,而且更直接。 - Ontropy

10

也适用于Linux,但它从终端读取而不是标准输入(这可能是一个管道)。 - hoijui

2

在原始模式下,您可以从终端读取单个键盘按键。 这里 有一个软件包,应该为您的程序提供原始终端模式。注意:此软件包仅适用于Linux。


0

1
这段代码演示了如何使用 SetConsoleMode。如果想要显示 "按 Enter 继续",那么 os.Stdin.Read([]byte{0}) 就足够了。 - kbridge4096

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接