📑

[1分学習]Goで標準入力を受け付ける

2021/03/18に公開

はじめに

こんにちは、Rabeeです。

突然ですが、スクリプト実行時にユーザーからの入力値を受け取って処理を分岐したいことってありますよね。
例えば、こんな感じ。

$ go run main.go
continue? (Y/n) > 

そこで今回は、先日スクリプトを作成する際に調査した標準入力の取得方法をまとめていきます。

標準入力の受付方法を調べていくと、いくつか種類があり
bufioパッケージやfmtパッケージで実装できることがわかりました。

結論

何も入力せずエンターキーが押されたことを検知したかったので、
bufioパケージを利用することにしました!
https://golang.org/pkg/bufio/#Scanner.Scan

  • サンプルコード
fmt.Print("continue? (Y/n) >")
scanner := bufio.NewScanner(os.Stdin)
for {
	scanner.Scan()
	in = scanner.Text()
	fmt.Println("in: ", in)
	switch in {
	case "", "Y":
		fmt.Println("デフォルトの処理をします")
		goto L
	case "n":
		fmt.Println("何もしない")
		goto L
	default:
		fmt.Println("コマンドが不正なのでもう一度入力を促す")
		continue
	}
}
L:
  • 実行結果
// エンターキー押下した場合
continue? (Y/n) >
in:  
デフォルトの処理をします

// Y入力した場合
continue? (Y/n) >Y
in:  Y
デフォルトの処理をします

// n入力した場合
continue? (Y/n) > n
in:  n
何もしない

// hoge入力した場合
continue? (Y/n) >hoge
in:  hoge
コマンドが不正なのでもう一度入力を促す

他の方法

fmtパッケージでも標準入力を受け付けることができます。
ただしこちらは、スペース区切りで複数の文字列を取得する方法で、
今回実装したかった「何も入力せずエンターキーが押されたことを検知」ができないため見送りました。

サンプルコードで挙動を確認していきましょう。

fmt.Scan

スペース区切りの文字列を取得することができ、事前に定義した数の入力を受け付けるまで繰り返し入力モードを維持します。
エンターキーはスペースとして認識されます。
https://golang.org/pkg/fmt/#Scan

  • サンプルコード
fmt.Print("fmt.Scan >")
var in1, in2, in3 string
n, err = fmt.Scan(&in1, &in2, &in3) // 3つの入力値を受け付ける
if err != nil {
    panic(err)
}
fmt.Println("in1: ", in1)
fmt.Println("in2: ", in2)
fmt.Println("in3: ", in3)
fmt.Println("n: ", n)
  • 実行結果
// スペース区切りで入力した場合
fmt.Scan >a b c
in1:  a
in2:  b
in3:  c
n:  3

// エンター区切りで入力した場合
fmt.Scan >a
b
c
in1:  a
in2:  b
in3:  c
n:  3

fmt.Scanln

fmt.Scanに似ていて、スペースキーで区切られた文字入力を受け付けますが、
エンターキーが押された時点で入力が確定されます。
予定している入力数よりも少ない場合はエラーになります。
https://golang.org/pkg/fmt/#Scanln

  • サンプルコード
fmt.Print("fmt.Scanln >")
var in1, in2, in3 string
n, err = fmt.Scanln(&in1, &in2, &in3) // 3つの入力値を受け付ける
if err != nil {
    panic(err)
}
fmt.Println("in1: ", in1)
fmt.Println("in2: ", in2)
fmt.Println("in3: ", in3)
fmt.Println("n: ", n)
  • 実行結果
// スペース区切りで入力した場合
fmt.Scanln >a b c
in1:  a
in2:  b
in3:  c
n:  3

// 予定している入力数に満たない場合はエラーが発生
fmt.Scanln >a
panic: unexpected newline

最後に

動くサンプルコードはこちら
https://play.golang.org/p/tfSVS5w8uwp

以上です。

(公開したら文字数的に2minになってしまった〜)

Discussion