こんにちは。
Go言語で標準入力から1行ごとではなく、1文字ずつ取得する方法を知りたいです。Enterではなく、1文字入力するごとにfmt.Println
で出力しようと思っているのですが、どのようにすればいいのかわかりません。
ご教授、お願いいたします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答2件
0
注意:ここに書いたのは連続する標準入力を一文字づつ処理する方法です。
ターミナルは基本の挙動がEnter押すごとに標準入力に投入します。
ASCII文字しか扱わないなら1バイト長のbyteスライスを引数にしたReadでOKです。
go
1b := []byte{0} 2_, err := os.Stdio.Read(b) 3...
ただこれだと、ASCII以外の文字で1文字づつになりません。
こういった場合でも正しく「1文字」ずつ読みたいのなら、
例えばbufio.ReaderのReadRuneを使います。
go
1package main 2 3import ( 4 "bufio" 5 "fmt" 6 "io" 7 "log" 8 "os" 9) 10 11func main() { 12 reader := bufio.NewReader(os.Stdin) 13 for { 14 r, _, err := reader.ReadRune() 15 if err != nil { 16 if err == io.EOF { 17 return 18 } 19 log.Fatal(err) 20 } 21 fmt.Println(string(r)) 22 } 23}
追記
質問者のコメントにあるような文字単位の入力をプログラムで受け取るには
OSのAPIを利用するか、以下のようにターミナルの動作モードを変えるしかなさそうです。
(以下の例はmacOSまたはLinux向けの方法です)
また、このモードではターミナルがCtrl+Cを受け取ってプロセスにSIGINTを送る機能も無効になるので
止めるには外部からシグナルを投げるかプログラム自身に終了処理が必要です。
https://play.golang.org/p/75GhzqTfV4_L
go
1package main 2 3import ( 4 "bufio" 5 "fmt" 6 "io" 7 "log" 8 "os" 9 "os/exec" 10 "os/signal" 11) 12 13func main() { 14 cmd := exec.Command("stty", "raw") 15 cmd.Stdin = os.Stdin 16 cmd.Run() 17 defer func() { 18 cmd := exec.Command("stty", "-raw") 19 cmd.Stdin = os.Stdin 20 cmd.Run() 21 }() 22 reader := bufio.NewReader(os.Stdin) 23 sig := make(chan os.Signal, 1) 24 signal.Notify(sig, os.Interrupt) 25 go func() { 26 defer close(sig) 27 for { 28 r, _, err := reader.ReadRune() 29 if err != nil { 30 if err == io.EOF { 31 return 32 } 33 log.Fatal(err) 34 } 35 if r == 'q' { 36 break 37 } 38 fmt.Println(string(r)) 39 } 40 }() 41 <-sig 42}
投稿2020/09/13 12:25
編集2020/09/14 00:42総合スコア3367
0
こういうことでしょうか。
go
1package main 2 3import ( 4 "fmt" 5 "log" 6 7 "github.com/mattn/go-tty" 8) 9 10func main() { 11 tty, err := tty.Open() 12 if err != nil { 13 log.Fatal(err) 14 } 15 defer tty.Close() 16 17 for { 18 r, err := tty.ReadRune() 19 if err != nil { 20 log.Fatal(err) 21 } 22 fmt.Println("Key press => " + string(r)) 23 } 24}
//go.mod module sample/tty go 1.16 require github.com/mattn/go-tty v0.0.3
shellsession
1$ go run . 2Key press => a 3Key press => b 4Key press => c 5Key press => d 6Key press => e 7...(ctrl+c) 8signal: interrupt 9$
かの mattn さんの go-tty
を使って、私の x86_64 系 *nix でビルドされたバイナリ動きました。未検証ですが Windows でもイケるらしいですよ。
- https://github.com/mattn/go-tty by mattn さん @ GitHub
動作確認済み環境:
- macOS Catalina(10.15.7), Linux 上で darwin 用にビルドしたバイナリ実行
- Debian GNU/Linux 10 (buster), go version go1.16.2 linux/amd64
- Alpine Linux v3.13, go version go1.16 linux/amd64
投稿2021/03/15 11:26
総合スコア15
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2020/09/13 13:27
2020/09/13 21:59
退会済みユーザー
2020/09/14 08:57