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

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

このコミットは、Go言語の公式ドキュメントである doc/effective_go.html に対するマイナーな更新を含んでいます。このファイルは、Go言語を効果的に記述するためのベストプラクティス、慣用的な表現、および言語の機能に関する詳細なガイドを提供します。今回の変更は、既存のコンテンツの明確化、正確性の向上、および新しい情報の追加に焦点を当てています。

コミット

このコミットは、doc/effective_go.html ファイルに対して、主に説明の明確化、例の改善、およびGo言語の特定の機能に関する詳細情報の追加を行っています。具体的には、Goのパッケージドキュメントにおける実行可能な例の利用方法、gofmtによるフォーマットの慣習、godocのコメント解釈と検索機能、命名規則、セミコロン挿入規則の注意点、変数再宣言と再代入の挙動、forループでのUTF-8処理、および型スイッチの慣用的な使用法に関する記述が更新されています。

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

https://github.com/golang/go/commit/6bfec725cfaa8c57f5a35c3f2a27880d808fe102

元コミット内容

doc/effective_go.html: minor updates, part 1

R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/7454044

変更の背景

effective_go.html は、Go言語の設計思想と効果的なプログラミングスタイルを伝えるための重要なドキュメントです。時間の経過とともに、言語の進化、コミュニティのベストプラクティスの確立、およびユーザーからのフィードバックに基づいて、ドキュメントの更新が必要になります。このコミットは、「minor updates, part 1」とあるように、一連のドキュメント改善作業の一部として行われたと考えられます。目的は、読者がGo言語をより深く理解し、より慣用的で効率的なコードを書けるように、既存の説明をより正確に、より分かりやすくすることにあります。特に、Goのユニークな機能(セミコロン挿入、godocの挙動、rangeとUTF-8など)に関する誤解を解消し、より実践的なガイダンスを提供することが意図されています。

前提知識の解説

  • gofmt: Go言語の公式フォーマッタ。コードのスタイルを統一し、可読性を高めるために使用されます。effective_go.htmlでは、gofmtによって自動的に挿入されるセミコロンの挙動や、括弧の省略など、Goの構文上の特徴と関連付けて説明されています。
  • godoc: Go言語のドキュメンテーションツール。ソースコードからドキュメントを生成し、Webサーバーとして提供することもできます。godocは、コメントの書き方や、エクスポートされた識別子の命名規則がドキュメントの生成と検索にどのように影響するかを理解する上で重要です。特に、コメントが識別子名で始まる慣習は、godocの出力をgrepでフィルタリングする際に役立つと説明されています。
  • Goのセミコロン挿入規則: Go言語では、C言語のように文の終わりにセミコロンを必要としますが、ソースコード上ではほとんどの場合、セミコロンを明示的に記述する必要がありません。これは、Goの字句解析器が特定の規則に基づいて自動的にセミコロンを挿入するためです。この規則は、コードの記述を簡潔にする一方で、改行の位置によっては予期せぬ挙動を引き起こす可能性があるため、特に制御構造の開始ブレースの位置に関する注意が必要です。
  • rangeキーワード: Goのforループでスライス、配列、文字列、マップ、チャネルをイテレートするために使用されます。文字列に対してrangeを使用すると、UTF-8エンコードされた文字列からUnicodeコードポイント(ルーン)を正しく抽出し、その開始バイト位置とルーン値を返します。不正なUTF-8シーケンスはU+FFFD(Replacement Character)として処理されます。
  • 型スイッチ (Type Switch): インターフェース型の変数が実行時に保持している具体的な型に基づいて異なる処理を行うためのGoの制御構造です。switch v := i.(type) の形式で記述され、各case節内で変数vは対応する具体的な型を持つようになります。このコミットでは、型スイッチ内で同じ変数名を再利用する慣用的なパターンが強調されています。
  • 命名規則とエクスポート: Goでは、識別子(変数、関数、型など)の最初の文字が大文字であるか小文字であるかによって、その識別子がパッケージ外にエクスポートされるか(大文字)、パッケージ内でのみ使用可能か(小文字)が決まります。この規則は、パッケージのAPI設計において非常に重要です。また、パッケージ名を考慮した簡潔な命名(例: bufio.ReaderではなくReader)が推奨されます。
  • import .: パッケージをインポートする際に、パッケージ名を省略してそのパッケージのエクスポートされた識別子を直接参照できるようにする特殊なインポート形式です。このコミットでは、主にテスト目的以外では使用を避けるべきであると改めて強調されています。

技術的詳細

このコミットにおける技術的詳細は、Go言語のドキュメンテーション、コードスタイル、および特定の言語機能の挙動に関する深い理解を反映しています。

  1. ドキュメンテーションの改善:

    • 実行可能な例の強調: golang.org 上で直接実行できるコード例(strings.Mapの例など)の存在を明示的に言及することで、読者がGoの機能をインタラクティブに試せることを促しています。これは、ドキュメントが単なる静的な情報源ではなく、学習ツールとしての価値も持つことを示唆しています。
    • godocgrepの連携: godocが生成するドキュメントコメントが、宣言される名前で始まるという慣習が、grepのようなコマンドラインツールと組み合わせてドキュメントを検索する際にいかに強力であるかを具体例(godoc regexp | grep parse)を挙げて説明しています。これは、Goのツールチェーンが単体で機能するだけでなく、Unix哲学に基づいた他のツールともシームレスに連携するように設計されていることを示しています。
    • コメントのフォーマット: godocがインデントされたテキストを固定幅フォントで表示する機能に言及することで、コードスニペットをドキュメントコメント内に含める際のベストプラクティスを提示しています。
  2. 言語機能の正確な説明:

    • セミコロン挿入規則の明確化: セミコロン挿入規則の結果として、制御構造の開始ブレースを次の行に置くことができないという「結果 (consequence)」として説明を修正しています。これは、単なる「注意点 (caveat)」ではなく、言語設計上の必然的な挙動であることを強調しています。
    • rangeとUnicodeコードポイント: 文字列に対するrangeの挙動を「Unicode characters」から「Unicode code points」に修正し、より正確な用語を使用しています。さらに、不正なUTF-8エンコーディングを含む文字列の例を追加し、その場合にU+FFFD(Replacement Character)が生成されることを示すことで、rangeの堅牢なエラー処理を実証しています。これは、GoがUnicodeとUTF-8を第一級市民として扱っていることの表れです。
    • 変数再宣言とスコープ: if v := expr; ... のような短い変数宣言が、外側のスコープで既に宣言されている変数と同じ名前を持つ場合に新しい変数を宣言するという挙動について、より詳細な説明を追加しています。また、関数パラメータと戻り値のスコープが関数本体と同じであるという重要な注意点も追加されています。これは、Goのスコープ規則の微妙な点であり、理解しておくべき重要な側面です。
    • 型スイッチの慣用的な使用法: 型スイッチ内で同じ変数名を再利用する慣用的なパターンを導入しています。これにより、各case節内で変数がその特定の型に「再宣言」され、コードがより簡潔で読みやすくなることを示しています。これは、Goのインターフェースと型アサーションを効果的に使用するための重要なイディオムです。
  3. コードスタイルの推奨事項の洗練:

    • 命名規則: 長すぎる名前よりも、簡潔な名前と適切なドキュメントコメントの組み合わせがより価値があるという点を強調しています。これは、Goの「シンプルさ」と「明瞭さ」の哲学に合致しています。
    • import . の使用: import . の使用をテスト目的以外では避けるべきであるという推奨を強化しています。これは、名前空間の衝突を避け、コードの可読性を維持するための重要なガイドラインです。

これらの変更は、Go言語のドキュメントが単に機能の説明に留まらず、言語の設計思想、慣用的なプログラミングスタイル、およびツールチェーンの活用方法を深く掘り下げて説明しようとする継続的な努力を示しています。

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

このコミットは doc/effective_go.html ファイルのみを変更しています。以下に主要な変更箇所を抜粋し、その前後を示します。

1. 導入部分の更新 (実行可能な例の追加)

--- a/doc/effective_go.html
+++ b/doc/effective_go.html
@@ -41,8 +41,14 @@ The <a href="/src/pkg/">Go package sources</a>
 are intended to serve not
 only as the core library but also as examples of how to
 use the language.
+Moreover, many of the packages contain working, self-contained
+executable examples you can run directly from the
+<a href="http://golang.org">golang.org</a> web site, such as
+<a href="http://golang.org/pkg/strings/#example_Map">this one</a> (click
+on the word "Example" to open it up).
 If you have a question about how to approach a problem or how something
-might be implemented, they can provide answers, ideas and
+might be implemented, the documentation, code and examples in the
+library can provide answers, ideas and
 background.
 </p>

2. コメントとgodocの連携に関する説明の追加

--- a/doc/effective_go.html
+++ b/doc/effective_go.html
@@ -205,6 +211,33 @@ takes care of that.
 The comments are uninterpreted plain text, so HTML and other
 annotations such as <code>_this_</code> will reproduce <i>verbatim</i> and should
 not be used.
+One adjustment <code>godoc</code> does do is to display indented
+text in a fixed-width font, suitable for program snippets.
+The package comment for the
+<a href="http://golang.org/pkg/fmt/"><code>fmt</code> package</a> uses this to good effect.
+</p>
+
+<p>
+If the name always begins the comment, the output of <code>godoc</code>
+can usefully be run through <code>grep</code>.
+Imagine you couldn't remember the name "Compile" but were looking for
+the parsing function for regular expressions, so you ran
+the command,
+</p>
+
+<pre>
+$ godoc regexp | grep parse
+</pre>
+
+<p>
+If all the doc comments in the package began, "This function...", <code>grep</code>
+wouldn't help you remember the name. But because the package starts each
+doc comment with the name, you'd see something like this,
+which recalls the word you're looking for.
+</p>
+
+<pre>
+$ godoc regexp | grep parse
+    Compile parses a regular expression and returns, if successful, a Regexp
+    parsed. It simplifies safe initialization of global variables holding
+    cannot be parsed. It simplifies safe initialization of global variables
+$\n</pre>
+
 <p>
 Depending on the context, <code>godoc</code> might not even
 reformat comments, so make sure they look good straight up:

3. forループでのUTF-8処理の例の改善

--- a/doc/effective_go.html
+++ b/doc/effective_go.html
@@ -652,29 +697,30 @@ for _, value := range array {\
 
 <p>
 For strings, the <code>range</code> does more work for you, breaking out individual
-Unicode characters by parsing the UTF-8.
+Unicode code points by parsing the UTF-8.
 Erroneous encodings consume one byte and produce the
 replacement rune U+FFFD. The loop
 </p>
 <pre>
-for pos, char := range "日本語" {
-    fmt.Printf("character %c starts at byte position %d\n", char, pos)
+for pos, char := range "日本\x80語" { // \x80 is an illegal UTF-8 encoding
+    fmt.Printf("character %#U starts at byte position %d\n", char, pos)
 }\n</pre>
 <p>
 prints
 </p>
 <pre>
-character 日 starts at byte position 0
-character 本 starts at byte position 3
-character 語 starts at byte position 6
+character U+65E5 '日' starts at byte position 0
+character U+672C '本' starts at byte position 3
+character U+FFFD '' starts at byte position 6
+character U+8A9E '語' starts at byte position 7
 </pre>

4. 型スイッチの例の改善

--- a/doc/effective_go.html
+++ b/doc/effective_go.html
@@ -757,19 +803,23 @@ variable.  Such a <em>type switch</em> uses the syntax of a type
 assertion with the keyword <code>type</code> inside the parentheses.\n If the switch declares a variable in the expression, the variable will
 have the corresponding type in each clause.
+It's also idiomatic to reuse the name in such cases, in effect declaring
+a new variable with the same name but a different type in each case.
 </p>
 <pre>
-switch t := interfaceValue.(type) {
+var t interface{}
+t = functionOfSomeType()
+switch t := t.(type) {
 default:
-    fmt.Printf("unexpected type %T", t)  // %T prints type
+    fmt.Printf("unexpected type %T", t)       // %T prints whatever type t has
 case bool:
-    fmt.Printf("boolean %t\n", t)
+    fmt.Printf("boolean %t\n", t)             // t has type bool
 case int:
-    fmt.Printf("integer %d\n", t)
+    fmt.Printf("integer %d\n", t)             // t has type int
 case *bool:
-    fmt.Printf("pointer to boolean %t\n", *t)
+    fmt.Printf("pointer to boolean %t\n", *t) // t has type *bool
 case *int:
-    fmt.Printf("pointer to integer %d\n", *t)
+    fmt.Printf("pointer to integer %d\n", *t) // t has type *int
 }\n</pre>

コアとなるコードの解説

上記の変更箇所は、effective_go.html の各セクションにおける説明の精度と実用性を向上させることを目的としています。

  1. 導入部分の更新:

    • Goの公式ウェブサイトで提供されている「実行可能な例」への言及は、読者がGoの機能を実際に試すための手軽な方法があることを示し、学習体験を向上させます。
    • 「documentation, code and examples in the library」が問題解決の助けとなるという修正は、Goのエコシステム全体が学習リソースとして機能するというより包括的な視点を提供します。
  2. コメントとgodocの連携に関する説明の追加:

    • godocがインデントされたテキストを固定幅フォントで表示する機能は、ドキュメントコメント内にコードスニペットを埋め込む際の推奨されるフォーマットを示しています。これにより、生成されるドキュメントの可読性が向上します。
    • godocの出力がgrepと組み合わせて効果的に使用できるという新しいセクションは、Goのドキュメンテーション慣習が単にドキュメント生成のためだけでなく、開発者がコードベースを探索し、APIを理解するための強力なツールとしても機能することを示しています。これは、Goのツール設計における実用主義と効率性を強調しています。
  3. forループでのUTF-8処理の例の改善:

    • Unicode characters から Unicode code points への用語の変更は、Unicodeの概念をより正確に反映しています。Goのrune型はUnicodeコードポイントを表すため、この修正はより厳密な表現です。
    • 不正なUTF-8シーケンス(\x80)を含む文字列の例を追加し、その結果としてU+FFFD(Replacement Character)が生成されることを示すことで、rangeが不正な入力に対しても堅牢に動作し、予期せぬクラッシュを防ぐことを実証しています。これは、Goが国際化対応においていかに配慮されているかを示しています。
  4. 型スイッチの例の改善:

    • 型スイッチ内で同じ変数名 t を再利用する慣用的なパターンを導入し、各case節内で t がその特定の型を持つことを明示的にコメントで示しています。これは、Goの型スイッチをより簡潔かつ効果的に記述するためのベストプラクティスです。このパターンは、コードの重複を減らし、可読性を高めるのに役立ちます。

これらの変更は、Go言語のドキュメントが単なるリファレンスではなく、開発者がGoをより深く理解し、より良いコードを書くための実践的なガイドとなるよう、継続的に改善されていることを示しています。

関連リンク

参考にした情報源リンク