Menu

Go言語のPrintfとSprintf:fmtの書式指定子チートシート

Goのfmtパッケージが値を表示・整形する仕組みを解説します。Println、Printf、Sprintf、Errorfの違い、書式指定子の一覧(%v、%+v、%d、%s、%q、%f、%T、%wなど)、幅、精度、パディングまで。

このページのコードはエディタで実行できます - 編集してすぐに結果を確認できます。

fmt パッケージには表示関数のファミリーが3つあり、どのファミリーにも同じ3つの種類があります。

関数出力先書式
PrintPrintlnPrintf標準出力デフォルト、空白と改行付きのデフォルト、書式文字列
SprintSprintlnSprintf戻り値の string同じ3つのスタイル
FprintFprintlnFprintf任意の io.Writer(ファイル、バッファ、HTTPレスポンス)同じ3つのスタイル
Errorf戻り値の error書式文字列、加えてラップ用の %w

Println はオペランドの間に空白を入れ、最後に改行を付けます。Printf は何も付けないので、\n を自分で書きます。Print は、両側とも文字列でないオペランドの間にだけ空白を入れます。これはかなり意外な挙動なので、ほとんどのコードは PrintlnPrintf を使います。

書式指定子

汎用

指定子表示するもの出力例
%vデフォルトの形式の値{Ana 31 [admin]}
%+vフィールド名付きの構造体{Name:Ana Age:31 Tags:[admin]}
%#v値のGo構文表現main.User{Name:"Ana", Age:31, Tags:[]string{"admin"}}
%Tmain.User
%%パーセント記号そのもの%

デバッグのときに使うのは %+v です。構造体へのポインタはアドレスではなく &{...} として表示されます。マップはキーをソートして表示するので、マップの反復順がランダムでも出力は安定します。

整数

指定子意味fmt.Sprintf(verb, 255)
%d10進数255
%b2進数11111111
%o8進数377
%O0o 接頭辞付きの8進数0o377
%x / %X16進数(小文字または大文字)ff / FF
%#x0x 接頭辞付きの16進数0xff
%cそのコードポイントの文字ÿ
%qクォート付きの文字リテラル'ÿ'
%UUnicode形式U+00FF

浮動小数点数

指定子意味fmt.Sprintf(verb, 1234.5678)
%f10進数、デフォルトは小数点以下6桁1234.567800
%.2f10進数、小数点以下2桁1234.57
%e指数表記1.234568e+03
%g%e%f の短いほう、末尾のゼロなし1234.5678
%v%g と同じ1234.5678

%.2f は浮動小数点数の正確な2進数の値を丸めるので、fmt.Sprintf("%.2f", 2.675)2.67 になります。2.675に最も近いfloat64は2.675よりわずかに小さいからです。お金を浮動小数点数から整形してはいけません。セントを整数で持ちます。

文字列とバイト

指定子意味fmt.Sprintf(verb, "go\n")
%s文字列そのものgo と改行
%qダブルクォート付き、エスケープを表示"go\n"
%x各バイトの16進数676f0a
% x空白区切りの16進数67 6f 0a

[]byte%s を使うとテキストとして表示し、%v を使うと数値([104 105])を表示します。

その他の型

指定子表示するもの
%tbooltrue または false
%pポインタ、スライス、マップ、チャネル、関数0xc000012345 のようなアドレス
%werror(Errorf でのみ)エラーのメッセージ、さらにラップする

幅、精度、パディング

% と指定子の間に、フラグ、幅、精度を置けます。

効果
%5d幅5、右寄せ(左側を空白で埋める)
%-5d幅5、左寄せ
%05dゼロで埋める
%.2f小数点以下2桁
%8.2f幅8で小数点以下2桁
%.3s文字列の最大3文字
%+d常に符号を表示する
%*d幅を次の引数から取る

2.5%.0f で整形すると 2 になることに注意してください。ここでは0.5を偶数方向に丸めます。文字列の幅は表示上の桁数ではなくルーン数で数えるので、日本語などのCJK文字や絵文字では表の列がずれることがあります。可変長のテキストの列をそろえるなら、text/tabwriter が幅を測ってくれます。

引数のインデックス

%[n] は位置で引数を選ぶので、同じ引数を再利用できます。

fmt.Printf("%[2]s %[1]s\n", "world", "hello") // hello world
fmt.Printf("%d %[1]x %[1]b\n", 10)             // 10 a 1010

Errorfと%w

fmt.Errorf は書式文字列から error を作ります。%w を使うと別のエラーもラップするので、呼び出し側は元のエラーを検出できます。

呼び出し側が原因をチェックする必要がありそうなら %w を、意図的に隠すなら %v を使います。Go 1.20以降は、1つの Errorf 呼び出しに複数の %w を含められます。ラップについてはエラー処理のページで詳しく扱っています。

String()による独自の書式

String() string メソッドを持つ型は、%v%sPrintln での表示方法を自分で決められます。

%dString() を通らず、基底の数値を表示します。エラー型での同等のメソッドは Error() string で、String() より優先されます。

指定子が間違っているとき

fmt は書式が間違っていてもpanicしません。問題をその場に表示します。

fmt.Printf("%d\n", "oops")
fmt.Printf("%d %d\n", 1)
fmt.Printf("%d\n", 1, 2)
%!d(string=oops)
1 %!d(MISSING)
1
%!(EXTRA int=2)

何もクラッシュさせないので、この出力は本番環境まで届きがちです。go vet はビルド時に3つとも検出します。

./main.go:8:2: fmt.Printf format %d has arg "oops" of wrong type string
./main.go:9:2: fmt.Printf format %d reads arg #2, but call has 1 arg
./main.go:10:2: fmt.Printf call needs 1 arg but has 2 args

パフォーマンスについて

fmt はすべての引数を any として受け取り、実行時に型を調べます(構造体、スライス、マップではリフレクションを使います)。ログや出力には問題ありませんが、タイトなループでは差が出ます。数値を1つ変換するだけなら、strconv.Itoastrconv.FormatFloat のほうが Sprintf より高速です。ループで長い文字列を組み立てるなら、Sprintf の結果を連結するのではなく、fmt.Fprintf(&b, ...)strings.Builder に書き込みます。

よくある質問

GoのPrintln、Printf、Sprintfの違いは何ですか?

fmt.Println は引数を空白で区切り、最後に改行を付けて表示します。fmt.Printf は書式文字列に従って表示し、改行は付けません。fmt.SprintfPrintf と同じように整形しますが、表示せずに結果を文字列として返します。fmt.Errorf も同じことをして error を返します。

Goで構造体をフィールド名付きで表示するには?

%+v を使います:fmt.Printf("%+v\n", user){Name:Ana Age:31} と表示します。%v は値だけの {Ana 31} を、%#v は型を含むGoの構文 main.User{Name:"Ana", Age:31} を表示します。

Goで浮動小数点数を小数点以下2桁に整形するには?

%.2f を使います:fmt.Sprintf("%.2f", 3.14159)"3.14" を返します。列をそろえるなら幅を加えて %8.2f、左寄せならマイナス記号を付けて %-8.2f とします。strconv.FormatFloat(f, 'f', 2, 64) でも書式文字列なしで同じ結果が得られます。

fmt.Errorfの%wは何をするのですか?

%w はエラーを %v と同じように整形し、さらにそれをラップするので、新しいエラーが元のエラーを持ち運びます。その後 errors.Iserrors.As でラップされたエラーを見つけられます:err := fmt.Errorf("load config: %w", os.ErrNotExist) なら errors.Is(err, os.ErrNotExist) はtrueです。%wfmt.Errorf でしか使えません。

なぜ出力に%!d(string=...)と表示されるのですか?

書式指定子が引数の型と合っていません。たとえば %d に文字列を渡した場合です。fmt はpanicせずに、問題をその場に表示します:%!d(string=oops)。引数が足りないと %!d(MISSING)、多すぎると %!(EXTRA int=2) と表示されます。go vet はプログラムを実行する前に3つとも検出します。

Coddy programming languages illustration

Coddyでコードを学ぼう

始める