Функция Golang похожа на getchar
есть ли функция, как getchar
в состоянии обрабатывать вкладку нажмите в консоли? Я хочу сделать какое-то завершение в своем консольном приложении.
7 ответов
С getchar()
пример:
#include <stdio.h>
void main()
{
char ch;
ch = getchar();
printf("Input Char Is :%c",ch);
}
иди эквивалент:
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
reader := bufio.NewReader(os.Stdin)
input, _ := reader.ReadString('\n')
fmt.Printf("Input Char Is : %v", string([]byte(input)[0]))
// fmt.Printf("You entered: %v", []byte(input))
}
последняя прокомментированная строка просто показывает, что при нажатии tab
первый элемент-U + 0009 ('таблица символов').
getchar()
не подходит, поскольку он требует, чтобы пользователь нажал enter. Вам нужно что-то вроде getch()/ readline/ jLine ncurses, как упоминалось @miku. С этими, вы на самом деле ждать одного нажатия клавиши.
Итак, у вас есть несколько вариантов:
использовать
ncurses
/readline
привязка, например https://code.google.com/p/goncurses/ или эквивалент как https://github.com/nsf/termboxсвернуть свой собственный вижу http://play.golang.org/p/plwBIIYiqG в исходную точку
использовать
os.Exec
для запуска stty или jLine.
refs:
https://groups.google.com/forum/?fromgroups=#!topic/golang-nuts/zhBE5MH4n-Q
https://groups.google.com/forum/?fromgroups=#!topic/golang-nuts/S9AO_kHktiY
https://groups.google.com/forum/?fromgroups=#!topic/golang-nuts/icMfYF8wJCk
предполагая, что вы хотите unbuffered input (без необходимости нажимать enter), это делает работу в системах 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()
// restore the echoing state when exiting
defer 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)+")")
}
}
есть несколько проектов обертки вокруг GNU readline, например:
- https://bitbucket.org/binet/go-readline/src
- https://github.com/igoralmeida/readline-go/blob/master/readline.go
но я не уверен, насколько они функциональны. Другим способом может быть эмуляция терминала, см.:
спасибо Paul Rademacher-это работает (по крайней мере, на Mac):
package main
import (
"bytes"
"fmt"
"github.com/pkg/term"
)
func getch() []byte {
t, _ := term.Open("/dev/tty")
term.RawMode(t)
bytes := make([]byte, 3)
numRead, err := t.Read(bytes)
t.Restore()
t.Close()
if err != nil {
return nil
}
return bytes[0:numRead]
}
func main() {
for {
c := getch()
switch {
case bytes.Equal(c, []byte{3}):
return
case bytes.Equal(c, []byte{27, 91, 68}): // left
fmt.Println("LEFT pressed")
default:
fmt.Println("Unknown pressed", c)
}
}
return
}
попробуйте это:
https://github.com/paulrademacher/climenu/blob/master/getchar.go
другие ответы здесь не работали, и go-termbox слишком тяжелый (он хочет взять на себя все окно терминала).
1 - Вы можете использовать C.getch()
:
это работает в командной строке Windows, читает только один символ без ввода:
(Запустите выходной двоичный файл внутри оболочки (терминала), а не внутри трубы или редактора.)
package main
//#include<conio.h>
import "C"
import "fmt"
func main() {
c := C.getch()
fmt.Println(c)
}
2 - для Linux (протестировано на Ubuntu):
package main
/*
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
char getch(){
char ch = 0;
struct termios old = {0};
fflush(stdout);
if( tcgetattr(0, &old) < 0 ) perror("tcsetattr()");
old.c_lflag &= ~ICANON;
old.c_lflag &= ~ECHO;
old.c_cc[VMIN] = 1;
old.c_cc[VTIME] = 0;
if( tcsetattr(0, TCSANOW, &old) < 0 ) perror("tcsetattr ICANON");
if( read(0, &ch,1) < 0 ) perror("read()");
old.c_lflag |= ICANON;
old.c_lflag |= ECHO;
if(tcsetattr(0, TCSADRAIN, &old) < 0) perror("tcsetattr ~ICANON");
return ch;
}
*/
import "C"
import "fmt"
func main() {
fmt.Println(C.getch())
fmt.Println()
}
посмотреть:
что эквивалентно getch () & getche () в Linux?
почему я не могу найти на Linux?
3 - тоже работает, но нужно "войти":
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
r := bufio.NewReader(os.Stdin)
c, err := r.ReadByte()
if err != nil {
panic(err)
}
fmt.Println(c)
}
вы также можете использовать ReadRune:
reader := bufio.NewReader(os.Stdin)
// ...
char, _, err := reader.ReadRune()
if err != nil {
fmt.Println("Error reading key...", err)
}
руна похожа на символ, так как GoLang на самом деле не имеет символов, чтобы попытаться поддержать несколько языков/unicode/etc.