
こんにちは。よっしーです(^^)
本日は、Go言語を効果的に使うためのガイドラインについて解説しています。
背景
Go言語を学び始めて、より良いコードを書きたいと思い、Go言語の公式ドキュメント「Effective Go」を知りました。これは、いわば「Goらしいコードの書き方指南書」になります。単に動くコードではなく、効率的で保守性の高いコードを書くためのベストプラクティスが詰まっているので、これを読んだ時の内容を備忘として残しました。
Printing(出力)
整数の10進数表記のようなデフォルトの変換だけが必要な場合は、万能フォーマット%v
(”value”の意味)を使用できます;結果はPrint
とPrintln
が生成するものと全く同じです。さらに、このフォーマットは配列、スライス、構造体、マップでさえも含む任意の値を出力できます。以下は前のセクションで定義されたタイムゾーンマップの出力文です。
fmt.Printf("%v\n", timeZone) // または単に fmt.Println(timeZone)
これは以下の出力を提供します:
map[CST:-21600 EST:-18000 MST:-25200 PST:-28800 UTC:0]
マップの場合、Printf
とその仲間たちはキー順に辞書順で出力をソートします。
構造体を出力する際、修正されたフォーマット%+v
は構造体のフィールドに名前を注釈し、任意の値に対して代替フォーマット%#v
は値を完全なGo構文で出力します。
type T struct {
a int
b float64
c string
}
t := &T{ 7, -2.35, "abc\tdef" }
fmt.Printf("%v\n", t)
fmt.Printf("%+v\n", t)
fmt.Printf("%#v\n", t)
fmt.Printf("%#v\n", timeZone)
出力:
&{7 -2.35 abc def}
&{a:7 b:-2.35 c:abc def}
&main.T{a:7, b:-2.35, c:"abc\tdef"}
map[string]int{"CST":-21600, "EST":-18000, "MST":-25200, "PST":-28800, "UTC":0}
(アンパサンド記号に注意してください。)その引用符付き文字列フォーマットは、string
型または[]byte
型の値に適用される際に%q
を通じても利用できます。代替フォーマット%#q
は可能であればバッククォートを代わりに使用します。(%q
フォーマットは整数とルーンにも適用され、単一引用符のルーン定数を生成します。)また、%x
は整数に加えて文字列、バイト配列、バイトスライスにも働き、長い16進数文字列を生成し、フォーマット内にスペース(% x
)があればバイト間にスペースを入れます。
もう一つの便利なフォーマットは%T
で、これは値の型を出力します。
fmt.Printf("%T\n", timeZone)
出力:
map[string]int
カスタム型のデフォルトフォーマットを制御したい場合、必要なことは型にString() string
のシグネチャを持つメソッドを定義することだけです。我々の単純な型T
に対して、それは以下のようになるかもしれません。
func (t *T) String() string {
return fmt.Sprintf("%d/%g/%q", t.a, t.b, t.c)
}
fmt.Printf("%v\n", t)
以下の形式で出力するために:
7/-2.35/"abc\tdef"
(T
型の値とT
へのポインタの両方を出力する必要がある場合、String
のレシーバは値型でなければなりません;この例はポインタを使用しましたが、それは構造体型に対してより効率的で慣用的だからです。詳細については下記のポインタ対値レシーバのセクションを参照してください。)
解説
1. 万能フォーマット %v とは
%v
は「何でも出力できる魔法のフォーマット」です:
fmt.Printf("%v\n", 123) // 数値
fmt.Printf("%v\n", "hello") // 文字列
fmt.Printf("%v\n", []int{1,2,3}) // スライス
fmt.Printf("%v\n", timeZone) // マップ
これはfmt.Print
やfmt.Println
と同じ結果になります。
2. 構造体出力の3つのパターン
type T struct {
a int
b float64
c string
}
t := &T{7, -2.35, "abc\tdef"}
基本出力 %v
:
fmt.Printf("%v\n", t) // → &{7 -2.35 abc def}
値だけが表示されます。
フィールド名付き %+v
:
fmt.Printf("%+v\n", t) // → &{a:7 b:-2.35 c:abc def}
どのフィールドがどの値かが分かります。
Go構文形式 %#v
:
fmt.Printf("%#v\n", t) // → &main.T{a:7, b:-2.35, c:"abc\tdef"}
コードで書くときの形式で表示されます。
3. その他の便利なフォーマット
型を確認する %T
:
fmt.Printf("%T\n", timeZone) // → map[string]int
変数の型が何かを調べるのに便利です。
文字列の特殊表示 %q
:
fmt.Printf("%q\n", "abc\tdef") // → "abc\tdef"
エスケープ文字も見えるように表示されます。
16進数表示 %x
:
fmt.Printf("%x\n", "hello") // → 68656c6c6f
fmt.Printf("% x\n", "hello") // → 68 65 6c 6c 6f(スペース区切り)
4. カスタム出力形式の定義
自分で作った型の出力形式をカスタマイズできます:
type T struct {
a int
b float64
c string
}
// String メソッドを定義
func (t *T) String() string {
return fmt.Sprintf("%d/%g/%q", t.a, t.b, t.c)
}
t := &T{7, -2.35, "abc\tdef"}
fmt.Printf("%v\n", t) // → 7/-2.35/"abc\tdef"
重要なポイント:
String() string
メソッドを定義するだけ%v
で出力したときに、このメソッドが自動的に呼ばれる- デバッグ時やログ出力時に見やすくできる
5. 実際の活用例
デバッグ時:
fmt.Printf("変数の中身: %+v\n", myStruct) // フィールド名も見える
fmt.Printf("変数の型: %T\n", myVar) // 型を確認
設定値の確認:
fmt.Printf("設定: %#v\n", config) // Go構文で表示
バイナリデータの確認:
fmt.Printf("データ: % x\n", data) // 16進数でスペース区切り
このように、%v
とその仲間たちを使うことで、デバッグやログ出力が格段に楽になります。
おわりに
本日は、Go言語を効果的に使うためのガイドラインについて解説しました。

何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。
それでは、また明日お会いしましょう(^^)
コメント