从标准输入中读取一个字符(不需要按下回车键)

huangapple go评论104阅读模式
英文:

Read a character from standard input in Go (without pressing Enter)

问题

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

按任意键退出...

并且在我按下任意键时退出。

我该如何实现这个功能?

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

我正在运行的是MS Windows。

英文:

I want my app to show:

press any key to exit ...

And to exit when I press any key.

How can I achieve this?

Note: I have googled but all of what I've found needed to press <kbd>Enter</kbd> at the end. I want something like Console.ReadKey() in C#.

I am running MS Windows.

答案1

得分: 35

这是一个最小工作示例,适用于运行UNIX系统的用户:

package main

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

func main() {
    // 禁用输入缓冲
    exec.Command("stty", "-F", "/dev/tty", "cbreak", "min", "1").Run()
    // 不在屏幕上显示输入的字符
    exec.Command("stty", "-F", "/dev/tty", "-echo").Run()

    var b []byte = make([]byte, 1)
    for {
        os.Stdin.Read(b)
        fmt.Println("我得到了字节", b, "("+string(b)+")")
    }
}
英文:

This is a minimal working example for those running a UNIX system:

package main

import (
    &quot;fmt&quot;
    &quot;os&quot;
    &quot;os/exec&quot;
)

func main() {
    // disable input buffering
    exec.Command(&quot;stty&quot;, &quot;-F&quot;, &quot;/dev/tty&quot;, &quot;cbreak&quot;, &quot;min&quot;, &quot;1&quot;).Run()
    // do not display entered characters on the screen
    exec.Command(&quot;stty&quot;, &quot;-F&quot;, &quot;/dev/tty&quot;, &quot;-echo&quot;).Run()

    var b []byte = make([]byte, 1)
    for {
        os.Stdin.Read(b)
        fmt.Println(&quot;I got the byte&quot;, b, &quot;(&quot;+string(b)+&quot;)&quot;)
    }
}

答案2

得分: 14

termbox-go是一个轻量级的Go本地包,提供了一些基本的终端控制功能。包括以原始模式获取输入(逐个字符读取,而不是默认的行缓冲行为)。

它在不同系统上也有相当好的兼容性。

keyboard扩展了termbox-go,提供了一些额外的键盘功能,如多键快捷键和序列。

英文:

termbox-go is a light-weight Go-native package which offers some rudimentary terminal control. Including the ability to get input in raw mode (read one character at a time without the default line-buffered behaviour).

It also has fairly ok compatibility across different systems.

And keyboard extends termbox-go to give some additional keyboard functionality like multi-key shortcuts and sequences.

答案3

得分: 10

go-termbox非常庞大。它想要接管整个终端窗口。例如,它在启动时清除屏幕,这可能不是你想要的。

我在OSX上整理了这个。只是一个小小的getchar():

https://github.com/paulrademacher/climenu/blob/master/getchar.go

英文:

go-termbox is very heavyweight. It wants to take over the entire terminal window. For example, it clears the screen on startup, which may not be what you want.

I put this together on OSX. Just a tiny getchar():

https://github.com/paulrademacher/climenu/blob/master/getchar.go

答案4

得分: 10

你可以使用这个库(我的):https://github.com/eiannone/keyboard

这是一个获取单个按键的示例:

char, _, err := keyboard.GetSingleKey()
if (err != nil) {
    panic(err)
}
fmt.Printf("你按下了:%q\r\n", char)
英文:

You could use this library (mine): https://github.com/eiannone/keyboard

This is an example for getting a single keystroke:

char, _, err := keyboard.GetSingleKey()
if (err != nil) {
    panic(err)
}
fmt.Printf(&quot;You pressed: %q\r\n&quot;, char)

答案5

得分: 10

The package "golang.org/x/term" allows you to switch the stdin into raw mode to read each byte at a time.

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]))
}
英文:

The package "golang.org/x/term" allows you to switch the stdin into raw mode to read each byte at a time.

package main

import (
	&quot;fmt&quot;
	&quot;os&quot;

	&quot;golang.org/x/term&quot;
)

func main() {
	// switch stdin into &#39;raw&#39; 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(&quot;the char %q was hit&quot;, string(b[0]))
}

答案6

得分: 2

你可以在原始模式下从终端读取单个按键。这里是一个可以为你的程序提供原始终端模式的包。注意:它只适用于Linux。

英文:

You can read a single key-press from a terminal in raw mode. Here is a package that should provide raw terminal mode to your program. Catch: it's Linux only.

答案7

得分: 0

尝试这个 - http://play.golang.org/p/kg-QirlucY

只需在 func main 的末尾从 os.Stdin 中读取。

英文:

Try this - http://play.golang.org/p/kg-QirlucY.

Just read from the os.Stdin at the end of the func main

huangapple
  • 本文由 发表于 2013年3月1日 21:37:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/15159118.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定