概要
今回のブログポストではGolangが基本的提供する入出力パッケージであるfmt
について説明します。
- 公式サイト: fmt
このブログポストで紹介するソースコードは下記のリンクで見ることができます。
標準出力
Golangでfmt
を使う方法を調べるためmain.go
ファイルを生成して次のように修正します。
package main
import "fmt"
func main() {
var a int = 10
var b int = 20
var f float64 = 3.14
fmt.Print("a: ", a);
fmt.Println("b: ", b);
fmt.Printf("a: %d / f: %f\n", a, f);
}
プログラムを実行すると下記のような結果が表示されます。
a: 10b: 20
a: 10 / f: 3.140000
標準出力関数は下記のような特徴を持っています。
- Print(): 関数の入力値を出力して改行をしない。
- Println(): 関数の入力値を出力して改行をする。
- Printf(): フォーマット(Format)に合わせて入力値を出力する。
フォーマット
Printf
で使えるフォーマット(Format)は次のようです。
%v
: データに合わせて基本の形で出力%T
: データタイプを出力%t
: boolをtrue/falseで出力%d
: 整数%b
: 2進数で出力%c
: ユニコード文字で出力(整数だけ可能)%o
: 8進数で出力%O
: 前に8進数であることを表示するためOo
を付けて出力%x
: 16進数で値を出力。10以上の場合はa-fで表示%X
: 16진수로 값을 출력 10이상은 A-F로 표시%e
: 指数の形で実数を出力(実数だけ可能)%E
: 指数の形で実数を出力(実数だけ可能)%f
: 実数の値をそのまま出力(小数点6桁まで)%F
: 実数の値をそのまま出力%g
: 実数の値が大きい場合、指数の形で表示。小さい場合そのまま表示(6桁以上になると指数で表現)%G
: 実数の値が大きい場合、指数の形で表示。小さい場合そのまま表示%s
: 文字列を出力%q
: 特殊文字機能を使わなくそのまま文字列を出力(ex> \n, \t)
整数は次のようなフォーマットを使って並べ替えができます。
%5d
: 5桁に合わせて出力(右揃え)%05d
: 5桁に合わせて出力(0が追加される)%-5d
: 5桁に合わせて出力(左揃え)
これを確認するため次のようにコードそ修正します。
func main() {
a := 1
b := 10
c := 100
d := 1000
e := 10000
fmt.Printf("a: %5d\n", a)
fmt.Printf("b: %5d\n", b)
fmt.Printf("c: %5d\n", c)
fmt.Printf("d: %5d\n", d)
fmt.Printf("e: %5d\n", e)
fmt.Println()
fmt.Printf("a: %05d\n", a)
fmt.Printf("b: %05d\n", b)
fmt.Printf("c: %05d\n", c)
fmt.Printf("d: %05d\n", d)
fmt.Printf("e: %05d\n", e)
fmt.Println()
fmt.Printf("a: %-5d\n", a)
fmt.Printf("b: %-5d\n", b)
fmt.Printf("c: %-5d\n", c)
fmt.Printf("d: %-5d\n", d)
fmt.Printf("e: %-5d\n", e)
}
このコードを実装すると下記のような結果が表示されます。
a: 1
b: 10
c: 100
d: 1000
e: 10000
a: 00001
b: 00010
c: 00100
d: 01000
e: 10000
a: 1
b: 10
c: 100
d: 1000
e: 10000
標準入力
fmt
を使ってユーザの入力を貰えます。main.go
ファイルを次のように修正します。
package main
import "fmt"
func main() {
var a int
var b int
n, err := fmt.Scanln(&a, &b)
if err != nil {
fmt.Println(err)
} else {
fmt.Println(n, a, b)
}
}
修正したプログラムを実行すると他のプログラムとは違ってプログラムが終了されなく、カーソルが画面に表示されることが確認できます。そしたら、次のように入力してみます。
10 30
上のように入力すると下記のように結果が表示されることが確認できます。
2 10 30
Scanln
はユーザから入力して貰った値をパラメータで設定されたメモリ住所に保存して、入力して貰った数とエラーがある場合エラーをリターンします。
これ以外に、ユーザの入力を受けるためfmt
の関数は次のようです。
Scan()
: 標準入力で値を入力して貰う。Scanf()
: 標準入力でフォーマット(Format)の形で値を入力して貰う。Scanln()
: 標準入力で1行を読んで値を入力する。
Scan
で変数を渡す時、&
を使ってメモリ住所を渡します。Scan
はこのように受けたメモリ住所に入力した貰った値を保存します。
入力バッファを消す
もし、下記のようにユーザの入力を2回受けるプログラムがあるとします。
package main
import "fmt"
func main() {
var a int
var b int
n, err := fmt.Scanln(&a, &b)
if err != nil {
fmt.Println(err)
} else {
fmt.Println(n, a, b)
}
n, err = fmt.Scanln(&a, &b)
if err != nil {
fmt.Println(err)
} else {
fmt.Println(n, a, b)
}
}
当該プログラムを実行して次のように入力します。
3 a
そしたら入力した値とその値を保存する変数のタイプが違ってランタイムエラーが発生します。
expected integer
しかし、2回入力するようにプログラムを作成しましたが、2回目の入力は実行されなくエラーが発生して終了されます。
unexpected newline
これは最初エラーが発生した時、エラーが発生した時点の内容がまだバッファに保存され、そのバッファの内容がそのまま使えたので問題が発生しました。
この問題を解決するため、次のようにエラーが発生した場合、バッファを初期化する必要があります。
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
stdin := bufio.NewReader(os.Stdin)
var a int
var b int
n, err := fmt.Scanln(&a, &b)
if err != nil {
fmt.Println(err)
stdin.ReadString('\n')
} else {
fmt.Println(n, a, b)
}
n, err = fmt.Scanln(&a, &b)
if err != nil {
fmt.Println(err)
stdin.ReadString('\n')
} else {
fmt.Println(n, a, b)
}
}
エラーが発生したら、stdin.ReadString('\n')
を使って入力バッファから改行文字が出るまでバッファの内容を読んで、バッファを空にします。
完了
これでGolangの標準入出力に使えるfmt
パッケージについてみてみました。入力する時はScan
を使って出力する時はPrint
を使いますし、入力する時、エラーが発生すると、入力バッファを空にする必要があることを勉強しました。
私のブログが役に立ちましたか?下にコメントを残してください。それは私にとって大きな大きな力になります!
アプリ広報
Deku
が開発したアプリを使ってみてください。Deku
が開発したアプリはFlutterで開発されています。興味がある方はアプリをダウンロードしてアプリを使ってくれると本当に助かります。