回答編集履歴

1

コメントに対する追記

2020/09/14 00:42

投稿

nobonobo
nobonobo

スコア3367

test CHANGED
@@ -1,3 +1,9 @@
1
+ 注意:ここに書いたのは連続する標準入力を一文字づつ処理する方法です。
2
+
3
+ ターミナルは基本の挙動がEnter押すごとに標準入力に投入します。
4
+
5
+
6
+
1
7
  ASCII文字しか扱わないなら1バイト長のbyteスライスを引数にしたReadでOKです。
2
8
 
3
9
  ```go
@@ -69,3 +75,111 @@
69
75
  }
70
76
 
71
77
  ```
78
+
79
+
80
+
81
+ ## 追記
82
+
83
+
84
+
85
+ 質問者のコメントにあるような文字単位の入力をプログラムで受け取るには
86
+
87
+ OSのAPIを利用するか、以下のようにターミナルの動作モードを変えるしかなさそうです。
88
+
89
+ (以下の例はmacOSまたはLinux向けの方法です)
90
+
91
+ また、このモードではターミナルがCtrl+Cを受け取ってプロセスにSIGINTを送る機能も無効になるので
92
+
93
+ 止めるには外部からシグナルを投げるかプログラム自身に終了処理が必要です。
94
+
95
+
96
+
97
+ [https://play.golang.org/p/75GhzqTfV4_L](https://play.golang.org/p/75GhzqTfV4_L)
98
+
99
+ ```go
100
+
101
+ package main
102
+
103
+
104
+
105
+ import (
106
+
107
+ "bufio"
108
+
109
+ "fmt"
110
+
111
+ "io"
112
+
113
+ "log"
114
+
115
+ "os"
116
+
117
+ "os/exec"
118
+
119
+ "os/signal"
120
+
121
+ )
122
+
123
+
124
+
125
+ func main() {
126
+
127
+ cmd := exec.Command("stty", "raw")
128
+
129
+ cmd.Stdin = os.Stdin
130
+
131
+ cmd.Run()
132
+
133
+ defer func() {
134
+
135
+ cmd := exec.Command("stty", "-raw")
136
+
137
+ cmd.Stdin = os.Stdin
138
+
139
+ cmd.Run()
140
+
141
+ }()
142
+
143
+ reader := bufio.NewReader(os.Stdin)
144
+
145
+ sig := make(chan os.Signal, 1)
146
+
147
+ signal.Notify(sig, os.Interrupt)
148
+
149
+ go func() {
150
+
151
+ defer close(sig)
152
+
153
+ for {
154
+
155
+ r, _, err := reader.ReadRune()
156
+
157
+ if err != nil {
158
+
159
+ if err == io.EOF {
160
+
161
+ return
162
+
163
+ }
164
+
165
+ log.Fatal(err)
166
+
167
+ }
168
+
169
+ if r == 'q' {
170
+
171
+ break
172
+
173
+ }
174
+
175
+ fmt.Println(string(r))
176
+
177
+ }
178
+
179
+ }()
180
+
181
+ <-sig
182
+
183
+ }
184
+
185
+ ```