Golangで、パイプからの標準入力を受け付けつつ、さらにキーボードからの入力を別に受付させたいということがあった。 で、前に シェルスクリプトの場合だと/dev/ttyから受け付けすることができる 、という内容について記述したことがあったが、それと同じようにすることで実現できるようだ。

sample_keyinput_and_pipe.go
package main import ( "fmt" "io" "log" "os" "time" "golang.org/x/crypto/ssh/terminal" ) func readStdin() { buf := make([]byte, 1024) for { n, err := os.Stdin.Read(buf) if err != nil && err != io.EOF { log.Fatal(err) } fmt.Print("FROM STDIN:", string(buf[:n])) if err == io.EOF { return } } } func main() { // 標準入力からの読み取り(goroutine) go readStdin() // 表示が混ざるので、とりあえずsleep time.Sleep(10 * time.Millisecond) // promptの出力 fmt.Print("\nINPUT TTY:") // /dev/ttyを開く tty, err := os.Open("/dev/tty") if err != nil { log.Fatal(err) } defer tty.Close() // bufferにキーボードからの入力を出力 buf := make([]byte, 1024) n, err := tty.Read(buf) if err != nil && err != io.EOF { log.Fatal(err) } fmt.Print("\nFROM TTY:", string(buf[:n])) // passwordとして扱わせる // promptの出力 fmt.Print("\nINPUT TTY(Password):") result, err := terminal.ReadPassword(int(tty.Fd())) if err != nil && err != io.EOF { log.Fatal(err) } fmt.Print("\nFROM TTY(Password):", string(result)) }

使いどころはそんなになさそうだけど、標準入力を受け付けながらパスワード入力を受け付ける、などのときに役に立つだろう。 (Windowsの場合だとどうすればいいのだろう…?)