Go言語のfmt
パッケージに存在するPrintf
関数は書式を指定して標準出力に書き込みを行います。
C言語のprintf
に良く似ています。が、C言語には存在しない書式がいくつか加わっています。
その中の代表格として以下のような書式が存在しています。
%T
- 対象データの型情報を埋め込む
%v
- デフォルトフォーマットで対象データの情報を埋め込む
%+v
- 構造体を出力する際に、%vの内容にフィールド名も加わる
%#v
- Go言語のリテラル表現で対象データの情報を埋め込む
これらの書式は、デバッグの時などに利用すると力を発揮すると思われます。
具体的に上記の書式にいくつかデータをセットしてみて、どんな値が出力されるのかを確認してみます。
(最初のサンプル以外は、pakage
, import
等の記述は省略します)
整数値
package main import ( "fmt" ) func main() { valInt := 123 fmt.Printf("valInt[%%T] -> %T\n", valInt) fmt.Printf("valInt[%%v] -> %v\n", valInt) fmt.Printf("valInt[%%+v] -> %+v\n", valInt) fmt.Printf("valInt[%%#v] -> %#v\n", valInt) }
■実行結果
valInt[%T] -> int valInt[%v] -> 123 valInt[%+v] -> 123 valInt[%#v] -> 123
値そのものが出力されます
文字列
func main() { valStr := "hello golang" fmt.Printf("valStr[%%T] -> %T\n", valStr) fmt.Printf("valStr[%%v] -> %v\n", valStr) fmt.Printf("valStr[%%+v] -> %+v\n", valStr) fmt.Printf("valStr[%%#v] -> %#v\n", valStr) }
■実行結果
valStr[%T] -> string valStr[%v] -> hello golang valStr[%+v] -> hello golang valStr[%#v] -> "hello golang"
%#v
の時だけ、"(ダブルクォート)で囲った値が出力されるので、スペースを含む文字列の場合などに分かりやすいかもしれません
構造体
type Person struct { id int name string } func main() { person := Person{id: 1, name: "taro"} fmt.Printf("person[%%T] -> %T\n", person) fmt.Printf("person[%%v] -> %v\n", person) fmt.Printf("person[%%+v] -> %+v\n", person) fmt.Printf("person[%%#v] -> %#v\n", person) }
■実行結果
person[%T] -> main.Person person[%v] -> {1 taro} person[%+v] -> {id:1 name:taro} person[%#v] -> main.Person{id:1, name:"taro"}
フィールド名が出る書式(%+v
, %#v
)の方が分かりやすく感じます
構造体のポインタ
type Person struct { id int name string } func main() { ptrPerson := &Person{id: 1, name: "taro"} fmt.Printf("ptrPerson[%%T] -> %T\n", ptrPerson) fmt.Printf("ptrPerson[%%v] -> %v\n", ptrPerson) fmt.Printf("ptrPerson[%%+v] -> %+v\n", ptrPerson) fmt.Printf("ptrPerson[%%#v] -> %#v\n", ptrPerson) }
■実行結果
ptrPerson[%T] -> *main.Person ptrPerson[%v] -> &{1 taro} ptrPerson[%+v] -> &{id:1 name:taro} ptrPerson[%#v] -> &main.Person{id:1, name:"taro"}
対象がポインタであってもアドレスではなく実際の値が表示されます
配列
func main() { strArray := [3]string{"tokyo", "osaka", "fukuoka"} fmt.Printf("strArray[%%T] -> %T\n", strArray) fmt.Printf("strArray[%%v] -> %v\n", strArray) fmt.Printf("strArray[%%+v] -> %+v\n", strArray) fmt.Printf("strArray[%%#v] -> %#v\n", strArray) }
■実行結果
strArray[%T] -> [3]string strArray[%v] -> [tokyo osaka fukuoka] strArray[%+v] -> [tokyo osaka fukuoka] strArray[%#v] -> [3]string{"tokyo", "osaka", "fukuoka"}
配列内の全要素の内容が出力されています
スライス
func main() { strSlice := []string{"monkey", "cat", "dog", "man"} fmt.Printf("strSlice[%%T] -> %T\n", strSlice) fmt.Printf("strSlice[%%v] -> %v\n", strSlice) fmt.Printf("strSlice[%%+v] -> %+v\n", strSlice) fmt.Printf("strSlice[%%#v] -> %#v\n", strSlice) }
■実行結果
strSlice[%T] -> []string strSlice[%v] -> [monkey cat dog man] strSlice[%+v] -> [monkey cat dog man] strSlice[%#v] -> []string{"monkey", "cat", "dog", "man"}
配列とほぼ同様の出力内容になっています
マップ
type Person struct { id int name string } func main() { personMap := map[int]Person{ 1: Person{id: 1, name: "taro"}, 2: Person{id: 2, name: "jiro"}, 3: Person{id: 2, name: "hanako"}, } fmt.Printf("personMap[%%T] -> %T\n", personMap) fmt.Printf("personMap[%%v] -> %v\n", personMap) fmt.Printf("personMap[%%+v] -> %+v\n", personMap) fmt.Printf("personMap[%%#v] -> %#v\n", personMap) }
■実行結果
personMap[%T] -> map[int]main.Person personMap[%v] -> map[1:{1 taro} 2:{2 jiro} 3:{2 hanako}] personMap[%+v] -> map[2:{id:2 name:jiro} 3:{id:2 name:hanako} 1:{id:1 name:taro}] personMap[%#v] -> map[int]main.Person{3:main.Person{id:2, name:"hanako"}, 1:main.Person{id:1, name:"taro"}, 2:main.Person{id:2, name:"jiro"}}
マップ内の全要素の内容が出力されています
channel
func main() { ch := make(chan string, 5) ch <- "start" fmt.Printf("ch[%%T] -> %T\n", ch) fmt.Printf("ch[%%v] -> %v\n", ch) fmt.Printf("ch[%%+v] -> %+v\n", ch) fmt.Printf("ch[%%#v] -> %#v\n", ch) }
■実行結果
ch[%T] -> chan string ch[%v] -> 0x1219c3c0 ch[%+v] -> 0x1219c3c0 ch[%#v] -> (chan string)(0x1219c3c0)
channelに関してはあまり有用な情報は出力されないようです
関数
func main() { function := func(src int) string { return fmt.Sprintf("param is %d", src) } fmt.Printf("function[%%T] -> %T\n", function) fmt.Printf("function[%%v] -> %v\n", function) fmt.Printf("function[%%+v] -> %+v\n", function) fmt.Printf("function[%%#v] -> %#v\n", function) }
■実行結果
function[%T] -> func(int) string function[%v] -> 0x476e20 function[%+v] -> 0x476e20 function[%#v] -> (func(int) string)(0x476e20)
関数に関しても出力することはできますが、%v
では有用な情報は出力されません
補足
本エントリでは全てPrintf
関数を用いているので結果が標準出力に書き込まれますが、Sprintf
関数を使用すればフォーマットした結果を戻り値で受け取ることができます