Как поймать нажатие клавиши без входа в цикл Голанга - PullRequest
0 голосов
/ 29 января 2019

У меня есть цикл, в котором некоторые вещи происходят в соответствии с состоянием, в котором он работает (ручной / автоматический / обучение).Теперь я хочу позволить программе переключаться между этими состояниями, нажимая сопровождающие буквы на клавиатуре («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) без необходимости нажимать ввод после?

Ответы [ 2 ]

0 голосов
/ 29 января 2019

Хорошо, после прочтения о os.Stdin.Read () и поиска этого ответа я создал следующий код:

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

Это работает как шарм, поэтому я простоотправка для любых будущих читателей.

Независимо, я желаю вам прекрасного дня!

0 голосов
/ 29 января 2019

Поскольку вы используете ReadString, который ожидает, какой бы параметр вы не указали, в вашем случае - клавишу return.Согласно документы :

ReadString читает до первого появления разделителя во входных данных, возвращая строку, содержащую данные вплоть до разделителя и включительно.

Это означает, что метод не вернется, пока вы не нажмете клавишу return.

Вместо этого вы можете использовать обычный метод Read , чтобы прочитать нужные вам символы.См. Также этот вопрос Stackoverflow для справки.

...