Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 18885] ファイルの概要

このコミットは、Go言語のfmtパッケージのドキュメントを更新し、GoStringerインターフェースの動作と、スライスや構造体のような複合オブジェクトに対するフォーマット動詞の適用方法について明確化するものです。特に、%q動詞が文字列スライスの各要素をクォートする挙動が明記されていなかった点を修正しています。

コミット

commit 0de0de0907a9e7b644ce0ce8f9862b4d70f531c7
Author: Rob Pike <r@golang.org>
Date:   Tue Mar 18 11:25:04 2014 +1100

    fmt: document GoStringer and explain application of formats to compound objects
    %q quotes each element of a string slice; this was never explained in the docs.
    Fixes #7015.
    
    LGTM=josharian
    R=golang-codereviews, josharian
    CC=golang-codereviews
    https://golang.org/cl/77140044

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/0de0de0907a9e7b644ce0ce8f9862b4d70f531c7

元コミット内容

fmt: document GoStringer and explain application of formats to compound objects
%q quotes each element of a string slice; this was never explained in the docs.
Fixes #7015.

変更の背景

このコミットは、Go言語のfmtパッケージのドキュメントにおける2つの重要な説明不足を解消するために行われました。

  1. GoStringerインターフェースのドキュメント化: fmtパッケージには、Stringerインターフェースと同様に、カスタムフォーマットを可能にするGoStringerインターフェースが存在します。しかし、その存在と、特に%#v動詞と組み合わせて使用された場合の挙動について、公式ドキュメントに明確な記述がありませんでした。これにより、開発者がGoStringerの機能を理解し、適切に利用することが困難でした。
  2. 複合オブジェクトに対するフォーマット動詞の適用規則の明確化: fmtパッケージのフォーマット動詞(例: %q, %vなど)が、スライスや構造体のような複合データ型に適用される際に、その動詞がオブジェクト全体に適用されるのか、それとも個々の要素に再帰的に適用されるのかが不明確でした。特に、文字列スライスに対して%q(クォートされた文字列)動詞を使用した場合、スライス全体がクォートされるのではなく、各文字列要素が個別にクォートされるという挙動は、ドキュメントに明記されていませんでした。この曖昧さが、開発者の混乱を招く可能性がありました。

これらの問題は、Go issue #7015として報告されており、このコミットはその問題を解決することを目的としています。ドキュメントの改善により、fmtパッケージの挙動がより予測可能になり、開発者が意図した通りの出力を得やすくなることが期待されます。

前提知識の解説

このコミットを理解するためには、Go言語のfmtパッケージと、関連するインターフェースおよびフォーマット動詞に関する知識が必要です。

fmtパッケージ

fmtパッケージは、Go言語におけるフォーマットI/O(入出力)を実装するためのパッケージです。C言語のprintfscanfに似た機能を提供し、様々なデータ型を整形して文字列として出力したり、文字列からデータを解析したりすることができます。

主な関数には以下のようなものがあります。

  • fmt.Print, fmt.Println, fmt.Printf: 標準出力への出力
  • fmt.Sprint, fmt.Sprintln, fmt.Sprintf: 文字列への出力
  • fmt.Fprint, fmt.Fprintln, fmt.Fprintf: io.Writerへの出力

フォーマット動詞 (Verbs)

Printf系の関数では、フォーマット文字列内で%に続く文字(動詞)を使って、出力する値の型や表示形式を指定します。

  • %v (value): 値のデフォルト表現。構造体やスライスなど、あらゆる型に対応します。
  • %#v (Go-syntax value): 値のGo言語の構文表現。構造体のフィールド名や型情報も表示され、デバッグに役立ちます。
  • %q (quoted string): 文字列をダブルクォートで囲み、Go言語の文字列リテラルとしてエスケープします。
  • %s (string): 文字列。
  • %d (decimal integer): 10進数整数。
  • %f (floating-point): 浮動小数点数。

Stringerインターフェース

fmtパッケージは、カスタム型がどのように文字列として表現されるかを制御するためのStringerインターフェースを定義しています。

type Stringer interface {
    String() string
}

ある型がString() stringメソッドを実装している場合、%vなどの動詞でその型の値をフォーマットしようとすると、String()メソッドが呼び出され、その戻り値が使用されます。

Formatterインターフェース

Formatterインターフェースは、Stringerよりもさらに詳細なフォーマット制御を可能にします。

type Formatter interface {
    Format(f fmt.State, c rune)
}

Formatメソッドは、フォーマットの状態(フラグ、幅、精度など)と、使用された動詞(c)を受け取ります。これにより、開発者は特定のフォーマット動詞やフラグに応じて、値の表現を細かくカスタマイズできます。

GoStringerインターフェース

このコミットでドキュメントが追加されたGoStringerインターフェースは、Stringerに似ていますが、特に%#v動詞が使用された場合に呼び出されます。

type GoStringer interface {
    GoString() string
}

GoString()メソッドは、その値のGo言語の構文表現を返すことを意図しています。これは、デバッグ出力や、コード生成などでGoのコードスニペットを生成する際に特に有用です。

技術的詳細

このコミットは、src/pkg/fmt/doc.goファイル、つまりfmtパッケージの公式ドキュメントに記述を追加することで、前述の2つの説明不足を解消しています。

GoStringerインターフェースに関する記述の追加

変更前は、Formatterインターフェースについてのみ言及されていましたが、変更後にはGoStringerインターフェースについても追記されました。

@@ -115,7 +115,9 @@
 	will print 23.
 
 	If an operand implements interface Formatter, that interface
-	can be used for fine control of formatting.
+	can be used for fine control of formatting. Similarly, if an
+	operand implements the GoStringer interface, that will be
+	invoked if the '%#v' verb is used to format the operand.

この変更により、Formatterと同様にGoStringerインターフェースが存在し、特に%#v動詞が使用された場合にGoString()メソッドが呼び出されることが明確に示されました。これにより、開発者は%#vの挙動をより深く理解し、カスタム型に対してGo言語の構文表現を提供する方法を学ぶことができます。

複合オブジェクトに対するフォーマット動詞の適用規則の明確化

最も重要な変更点の一つは、スライスや構造体のような複合オブジェクトに対するフォーマット動詞の適用規則に関する新しい段落の追加です。

@@ -128,6 +130,12 @@
 	will be used to convert the object to a string, which will then
 	be formatted as required by the verb (if any).
 
+	For compound operands such as slices and structs, the format
+	applies to the elements of each operand, recursively, not to the
+	operand as a whole. Thus %q will quote each element of a slice
+	of strings, and %6.2f will control formatting for each element
+	of a floating-point array.
+
 	To avoid recursion in cases such as
 	        type X string
 	        func (x X) String() string { return Sprintf("<%s>", x) }

この新しい段落は、以下の重要な規則を明確にしています。

  • 再帰的な適用: スライスや構造体のような複合オペランドの場合、フォーマットはオペランド全体ではなく、その各要素に再帰的に適用されます。
  • 具体例:
    • %qは文字列スライスの各要素をクォートします。例えば、[]string{"a", "b"}%qでフォーマットすると、["a" "b"]のような出力になります(実際には["a", "b"]のようにカンマ区切りで出力されますが、各要素がクォートされる点が重要です)。
    • %6.2fは浮動小数点数配列の各要素のフォーマットを制御します。例えば、[]float64{1.234, 5.678}%6.2fでフォーマットすると、[ 1.23 5.68]のような出力になります。

この明確化により、開発者は複合オブジェクトをフォーマットする際のfmtパッケージの挙動を正確に予測できるようになり、予期せぬ出力やバグを防ぐことができます。

コアとなるコードの変更箇所

--- a/src/pkg/fmt/doc.go
+++ b/src/pkg/fmt/doc.go
@@ -115,7 +115,9 @@
 	will print 23.
 
 	If an operand implements interface Formatter, that interface
-	can be used for fine control of formatting.
+	can be used for fine control of formatting. Similarly, if an
+	operand implements the GoStringer interface, that will be
+	invoked if the '%#v' verb is used to format the operand.
 
 	If the format (which is implicitly %v for Println etc.) is valid
 	for a string (%s %q %v %x %X), the following two rules also apply:
@@ -128,6 +130,12 @@
 	will be used to convert the object to a string, which will then
 	be formatted as required by the verb (if any).\n
+\tFor compound operands such as slices and structs, the format
+\tapplies to the elements of each operand, recursively, not to the
+\toperand as a whole. Thus %q will quote each element of a slice
+\tof strings, and %6.2f will control formatting for each element
+\tof a floating-point array.\n
 \tTo avoid recursion in cases such as
 \t\ttype X string
 \t\tfunc (x X) String() string { return Sprintf("<%s>\", x) }\n

コアとなるコードの解説

このコミットは、src/pkg/fmt/doc.goファイル内のドキュメントコメントを修正しています。

  1. GoStringerに関する追加: 元のドキュメントでは、Formatterインターフェースがフォーマットの細かい制御に使用できると説明されていました。このコミットでは、その説明に続けて、GoStringerインターフェースも同様に機能し、特に%#v動詞が使用された場合に呼び出されることが追記されました。

    	If an operand implements interface Formatter, that interface
    	can be used for fine control of formatting. Similarly, if an
    	operand implements the GoStringer interface, that will be
    	invoked if the '%#v' verb is used to format the operand.
    

    この変更により、GoStringerの存在と、%#vとの関連性が明確になりました。

  2. 複合オブジェクトのフォーマットに関する説明の追加: このコミットの主要な変更点の一つは、複合オブジェクト(スライスや構造体)に対するフォーマット動詞の適用方法に関する新しい段落の追加です。

    	For compound operands such as slices and structs, the format
    	applies to the elements of each operand, recursively, not to the
    	operand as a whole. Thus %q will quote each element of a slice
    	of strings, and %6.2f will control formatting for each element
    	of a floating-point array.
    

    この段落は、フォーマット動詞が複合オブジェクト全体ではなく、その個々の要素に再帰的に適用されることを明確に述べています。そして、文字列スライスに対する%qの挙動と、浮動小数点数配列に対する%6.2fの挙動を具体例として挙げることで、この規則をより理解しやすくしています。これにより、開発者はfmtパッケージが複合データ型をどのように処理するかについて、より正確な期待を持つことができます。

これらの変更は、コードの動作自体を変更するものではなく、既存の動作に関するドキュメントの正確性と網羅性を向上させるものです。

関連リンク

参考にした情報源リンク