[インデックス 15600] ファイルの概要
このコミットは、Go言語の公式ドキュメント「Effective Go」(doc/effective_go.html
)に対する一連の軽微な編集の第3弾です。主な目的は、ドキュメントの明確性、正確性、および網羅性を向上させることです。具体的には、range
キーワードの文字列に対する挙動、rune
の概念、fmt
パッケージの書式設定、append
関数のシグネチャ、Goにおける定数の定義、メソッドのレシーバ、埋め込みフィールドのアクセス、チャネルの性質、そして特に「並行性(Concurrency)」と「並列性(Parallelism)」の重要な区別に関する説明が更新・追加されています。また、エラーハンドリングにおけるpanic
とrecover
の利用例も改善されています。
コミット
commit 5f07125cb9333e002a7ddd99a37c1db7645ebd9b
Author: Rob Pike <r@golang.org>
Date: Wed Mar 6 10:08:48 2013 -0800
effective_go.html: round 3 of minor edits.
R=golang-dev, iant
CC=golang-dev
https://golang.org/cl/7489044
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/5f07125cb9333e002a7ddd99a37c1db7645ebd9b
元コミット内容
effective_go.html: round 3 of minor edits.
R=golang-dev, iant
CC=golang-dev
https://golang.org/cl/7489044
変更の背景
このコミットは、「Effective Go」ドキュメントの継続的な改善プロセスの一環として行われました。ドキュメントはGo言語のベストプラクティスとイディオムを開発者に伝えるための重要なリソースであり、その内容は常に最新かつ正確である必要があります。今回の「round 3 of minor edits」という表現は、以前にも同様の小規模な修正が行われており、ドキュメントの品質を段階的に向上させるための継続的な取り組みであることを示唆しています。特に、Go言語の進化や、開発者が抱きやすい誤解(例:並行性と並列性の違い)を解消するために、説明の明確化と詳細化が求められていました。
前提知識の解説
このコミットの変更内容を理解するためには、以下のGo言語の基本的な概念とHTMLの知識が必要です。
range
キーワード: Go言語でスライス、配列、文字列、マップ、チャネルを反復処理するための構文です。文字列に対してrange
を使用すると、UTF-8でエンコードされた文字列からUnicodeのコードポイント(rune
)を効率的に取り出すことができます。- UnicodeとUTF-8: Unicodeは世界中の文字を統一的に扱うための文字コード標準であり、UTF-8はそのUnicode文字を可変長でエンコードするための方式です。Go言語の文字列はUTF-8でエンコードされています。
rune
: Go言語における単一のUnicodeコードポイントを表す組み込み型(int32
のエイリアス)です。文字列をrange
で反復処理する際に、各文字がrune
として返されます。fmt
パッケージ: Go言語の標準ライブラリで、書式付きI/O(入力/出力)を提供します。fmt.Println
、fmt.Fprint
、fmt.Sprintf
などの関数があり、様々なデータ型を整形して出力できます。io.Writer
インターフェース: データを書き込むための汎用的なインターフェースです。Write([]byte) (n int, err error)
メソッドを定義しています。os.Stdout
やos.Stderr
はio.Writer
インターフェースを実装しています。append
関数: スライスに要素を追加するための組み込み関数です。新しいスライスを返すことが特徴です。- 定数(Constants): Go言語における定数は、コンパイル時に値が決定される不変のデータです。数値、文字列、ブール値、そして
rune
(文字)が定数として定義できます。 - メソッド(Methods): 特定の型に関連付けられた関数です。レシーバ引数(receiver argument)を持つことで、その型の値に対して操作を行うことができます。レシーバは値型またはポインタ型にすることができます。
- 埋め込みフィールド(Embedded Fields): Goの構造体(struct)において、フィールド名なしで型を宣言することで、その型のメソッドやフィールドを外部から直接アクセスできるようにする機能です。これにより、コンポジション(composition)によるコードの再利用が容易になります。
- チャネル(Channels): ゴルーチン(goroutine)間で値を送受信するための通信メカニズムです。
make
関数で作成され、バッファの有無によって挙動が異なります。- バッファなしチャネル(Unbuffered Channels): 送信側と受信側が同時に準備ができたときにのみ通信が行われる同期的なチャネルです。
- バッファありチャネル(Buffered Channels): 指定された数の値をバッファに格納できるチャネルです。バッファが満杯になるまで送信はブロックされず、バッファが空になるまで受信はブロックされません。
panic
とrecover
: Go言語のエラーハンドリングメカニズムの一部です。panic
: プログラムの実行を停止させ、スタックを巻き戻す(unwind)機能です。通常、回復不可能なエラーや予期せぬ状況で使用されます。recover
:defer
関数内でpanic
からの回復を試みるための組み込み関数です。panic
が発生した際に、プログラムがクラッシュするのを防ぎ、エラーを処理する機会を提供します。
- 並行性(Concurrency)と並列性(Parallelism):
- 並行性: 複数のタスクが同時に進行しているように見えること(例:シングルコアCPUで複数のタスクを切り替えながら実行)。Go言語のゴルーチンとチャネルは並行性を実現するための強力なツールです。
- 並列性: 複数のタスクが実際に同時に実行されること(例:マルチコアCPUで複数のタスクを同時に実行)。並行性を持つプログラムが、マルチコア環境で並列に実行される可能性があります。
技術的詳細
このコミットでは、effective_go.html
の複数のセクションにわたって、Go言語の特定の機能に関する説明が改善されています。
-
range
とrune
の明確化:- 文字列に対する
range
がUTF-8を解析して個々のUnicodeコードポイントを生成することを強調し、rune
がGoにおける単一のUnicodeコードポイントの用語であることを明記しました。これにより、文字列処理におけるrune
の重要性がより明確になります。 rune
に関する言語仕様へのリンクが追加され、読者がさらに詳細な情報を参照できるようになりました。
- 文字列に対する
-
fmt
パッケージの書式設定の改善:fmt.Fprint
の説明が、「Tourで述べられているように」という間接的な表現から、「書式付き出力関数fmt.Fprint
」という直接的な表現に変更されました。これにより、ドキュメントの自己完結性が高まります。%q
書式指定子が文字列やバイトスライスだけでなく、整数やrune
にも適用され、単一引用符で囲まれたrune
定数として出力されることが追記されました。これは、%q
の汎用性を示す重要な情報です。
-
append
関数のシグネチャの修正:append
関数のHTML表示における型プレースホルダーの書式が修正されました。これは視覚的な正確性を高めるための小さな修正です。
-
初期化と定数の説明の強化:
- 初期化に関する説明で、「異なるパッケージ間の初期化されたオブジェクト間の問題」が「異なるパッケージ間であっても、初期化されたオブジェクト間の問題」と変更され、より包括的な表現になりました。
- 定数として利用可能な型に「文字(
rune
)」が追加されました。これにより、Goの定数が数値、文字列、ブール値だけでなく、文字も含むことが明確になりました。
-
String
メソッドとレシーバの適用範囲の拡張:String
メソッドをユーザー定義型にアタッチする能力が、任意のユーザー定義型に適用され、自動的な書式設定が可能になることを強調しました。特に、ByteSize
のようなスカラー型にも有用であることが追記され、その汎用性が示されました。- メソッドがポインタやインターフェース以外の任意の名前付き型に定義できることが、
ByteSize
の例を引用して再確認されました。
-
bytes.Buffer
の説明の精度向上:Write
をバイトスライスに適用するというアイデアが、「bytes.Buffer
によって実装されている」から「bytes.Buffer
の実装の中心である」に変更されました。これは、bytes.Buffer
がio.Writer
インターフェースを実装していることのより正確な表現です。
-
os.Args
の出力例の簡素化:ArgServer
関数の例で、os.Args
スライスをループで回して個々の引数を出力する代わりに、fmt.Println(os.Args)
やfmt.Fprintln(w, os.Args)
を使ってスライス全体を直接出力するように変更されました。これは、fmt
パッケージがスライスを適切に書式設定して出力できることを示しており、コードの簡潔化に貢献します。
-
埋め込みフィールドのアクセスと初期化の明確化:
Job
構造体内のLogger
埋め込みフィールドの初期化方法が、コンストラクタ内でどのように行われるか具体的に示されました。- 埋め込みフィールドへのアクセス(例:
job.Logger
)が、そのフィールドのメソッドを洗練させる場合に有用であるという説明が追加されました。
-
チャネルの参照セマンティクスとバッファなしチャネルの同期性:
make
でチャネルを割り当てると、「結果の値が基になるデータ構造への参照として機能する」という説明が追加されました。これは、チャネルが参照型であることを明確にします。- バッファなしチャネルが「通信と同期を組み合わせる」という点が強調され、その同期的な性質がより明確に説明されました。
-
並行性 vs. 並列性の重要な区別:
- 並行性(Concurrency)と並列性(Parallelism)の概念的な違いを明確に説明する新しい段落が追加されました。Goが並行言語であり、並列言語ではないこと、そしてGoの並行性機能が一部の並列計算問題を構造化しやすくする一方で、すべての並列化問題がGoのモデルに適合するわけではないことが述べられています。この区別に関するブログ記事へのリンクも提供され、読者の理解を深めるための重要なリソースが示されました。
-
エラー文字列のプレフィックスの柔軟性:
- エラー文字列が「エラーを生成したパッケージ名をプレフィックスとして持つ」という説明が、「操作またはパッケージ名をプレフィックスとして持つ」に変更されました。これにより、エラーメッセージの命名規則に柔軟性がもたらされ、より具体的なコンテキストを示すことができるようになりました。
-
panic
とrecover
の挙動の修正と例の追加:- コンパイラが関数の終わりでの
panic
を認識し、return
ステートメントの通常のチェックを抑制するという記述が削除されました。これは、以前のドキュメントの誤解を招く可能性のある記述を修正したものです。 panic
とrecover
を用いたregexp
パッケージの例において、型アサーションがどのように機能し、予期せぬエラー(例:インデックス範囲外)が発生した場合にスタックの巻き戻しが継続されるかがより詳細に説明されました。re.error("'*' illegal at start of expression")
という具体的なコード例が追加され、error
メソッドの利用方法が視覚的に示されました。
- コンパイラが関数の終わりでの
これらの変更は、Go言語の重要な概念に対する読者の理解を深め、より正確な情報を提供することを目的としています。
コアとなるコードの変更箇所
変更はすべてdoc/effective_go.html
ファイル内で行われています。以下に、主要な変更箇所の差分を示します。
--- a/doc/effective_go.html
+++ b/doc/effective_go.html
@@ -699,7 +699,12 @@ for _, value := range array {\n For strings, the <code>range</code> does more work for you, breaking out individual\n Unicode code points by parsing the UTF-8.\n Erroneous encodings consume one byte and produce the\n-replacement rune U+FFFD. The loop\n+replacement rune U+FFFD.\n+(The name (with associated builtin type) <code>rune</code> is Go terminology for a\n+single Unicode code point.\n+See <a href=\"http://golang.org/ref/spec#Rune_literals\">the language specification</a>\n+for details.)\n+The loop\n </p>\n <pre>\n for pos, char := range \"日本\\x80語\" { // \\x80 is an illegal UTF-8 encoding\n@@ -1596,8 +1601,7 @@ fmt.Println(\"Hello\", 23)\n fmt.Println(fmt.Sprint(\"Hello \", 23))\n </pre>\n <p>\n-As mentioned in\n-the <a href=\"http://tour.golang.org\">Tour</a>, <code>fmt.Fprint</code>\n+The formatted print functions <code>fmt.Fprint</code>\n and friends take as a first argument any object\n that implements the <code>io.Writer</code> interface; the variables <code>os.Stdout</code>\n and <code>os.Stderr</code> are familiar instances.\n@@ -1663,8 +1667,10 @@ map[string] int{\"CST\":-21600, \"PST\":-28800, \"EST\":-18000, \"UTC\":0, \"MST\":-25200}\n <p>\n (Note the ampersands.)\n That quoted string format is also available through <code>%q</code> when\n-applied to a value of type <code>string</code> or <code>[]byte</code>;\n-the alternate format <code>%#q</code> will use backquotes instead if possible.\n+applied to a value of type <code>string</code> or <code>[]byte</code>.\n+The alternate format <code>%#q</code> will use backquotes instead if possible.\n+(The <code>%q</code> format also applies to integers and runes, producing a\n+single-quoted rune constant.)\n Also, <code>%x</code> works on strings, byte arrays and byte slices as well as\n on integers, generating a long hexadecimal string, and with\n a space in the format (<code>% x</code>) it puts spaces between the bytes.\n@@ -1762,7 +1768,7 @@ is different from our custom <code>Append</code> function above.\n Schematically, it\'s like this:\n </p>\n <pre>\n-func append(slice []<i>T</i>, elements...T) []<i>T</i>\n+func append(slice []<i>T</i>, elements...<i>T</i>) []<i>T</i>\n </pre>\n <p>\n where <i>T</i> is a placeholder for any given type. You can\'t\n@@ -1810,7 +1816,7 @@ would be wrong; <code>y</code> is not of type <code>int</code>.\n Although it doesn\'t look superficially very different from\n initialization in C or C++, initialization in Go is more powerful.\n Complex structures can be built during initialization and the ordering\n-issues between initialized objects in different packages are handled\n+issues among initialized objects, even among different packages, are handled\n correctly.\n </p>\n \n@@ -1820,7 +1826,7 @@ correctly.\n Constants in Go are just that—constant.\n They are created at compile time, even when defined as\n locals in functions,\n-and can only be numbers, strings or booleans.\n+and can only be numbers, characters (runes), strings or booleans.\n Because of the compile-time restriction, the expressions\n that define them must be constant expressions,\n evaluatable by the compiler. For instance,\n@@ -1838,9 +1844,11 @@ sets of values.\n </p>\n {{code \"/doc/progs/eff_bytesize.go\" `/^type ByteSize/` `/^\\)/`}}\n <p>\n-The ability to attach a method such as <code>String</code> to a\n-type makes it possible for such values to format themselves\n-automatically for printing, even as part of a general type.\n+The ability to attach a method such as <code>String</code> to any\n+user-defined type makes it possible for arbitrary values to format themselves\n+automatically for printing.\n+Although you\'ll see it most often applied to structs, this technique is also useful for\n+scalar types such as floating-point types like <code>ByteSize</code>.\n </p>\n {{code \"/doc/progs/eff_bytesize.go\" `/^func.*ByteSize.*String/` `/^}/`}}\n <p>\n@@ -1909,7 +1917,8 @@ func init() {\n \n <h3 id=\"pointers_vs_values\">Pointers vs. Values</h3>\n <p>\n-Methods can be defined for any named type that is not a pointer or an interface;\n+As we saw with <code>ByteSize</code>,\n+methods can be defined for any named type (except a pointer or an interface);\n the receiver does not have to be a struct.\n </p>\n <p>\n@@ -1970,7 +1979,7 @@ modifications to be discarded.\n </p>\n <p>\n By the way, the idea of using <code>Write</code> on a slice of bytes\n-is implemented by <code>bytes.Buffer</code>.\n+is central to the implementation of <code>bytes.Buffer</code>.\n </p>\n \n <h2 id=\"interfaces_and_types\">Interfaces and other types</h2>\n@@ -2205,9 +2214,7 @@ It\'s easy to write a function to print the arguments.\n </p>\n <pre>\n func ArgServer() {\n- for _, s := range os.Args {\n- fmt.Println(s)\n- }\n+ fmt.Println(os.Args)\n }\n </pre>\n <p>\n@@ -2243,9 +2250,7 @@ to have the right signature.\n <pre>\n // Argument server.\n func ArgServer(w http.ResponseWriter, req *http.Request) {\n- for _, s := range os.Args {\n- fmt.Fprintln(w, s)\n- }\n+ fmt.Fprintln(w, os.Args)\n }\n </pre>\n <p>\n@@ -2400,8 +2405,8 @@ log to the <code>Job</code>:\n job.Log(\"starting now...\")\n </pre>\n <p>\n-The <code>Logger</code> is a regular field of the struct and we can initialize\n-it in the usual way with a constructor,\n+The <code>Logger</code> is a regular field of the <code>Job</code> struct,\n+so we can initialize it in the usual way inside the constructor for <code>Job</code>, like this,\n </p>\n <pre>\n func NewJob(command string, logger *log.Logger) *Job {\n@@ -2416,10 +2421,12 @@ job := &Job{command, log.New(os.Stderr, \"Job: \", log.Ldate)}\n </pre>\n <p>\n If we need to refer to an embedded field directly, the type name of the field,\n-ignoring the package qualifier, serves as a field name. If we needed to access the\n+ignoring the package qualifier, serves as a field name, as it did\n+in the <code>Read</code> method of our <code>ReaderWriter</code> struct.\n+Here, if we needed to access the\n <code>*log.Logger</code> of a <code>Job</code> variable <code>job</code>,\n-we would write <code>job.Logger</code>.\n-This would be useful if we wanted to refine the methods of <code>Logger</code>.\n+we would write <code>job.Logger</code>,\n+which would be useful if we wanted to refine the methods of <code>Logger</code>.\n </p>\n <pre>\n func (job *Job) Logf(format string, args ...interface{}) {\n@@ -2535,7 +2542,8 @@ completion. For that, we need channels.\n <h3 id=\"channels\">Channels</h3>\n \n <p>\n-Like maps, channels are allocated with <code>make</code>.\n+Like maps, channels are allocated with <code>make</code>, and\n+the resulting value acts as a reference to an underlying data structure.\n If an optional integer parameter is provided, it sets the buffer size for the channel.\n The default is zero, for an unbuffered or synchronous channel.\n </p>\n@@ -2545,7 +2553,7 @@ cj := make(chan int, 0) // unbuffered channel of integers\n cs := make(chan *os.File, 100) // buffered channel of pointers to Files\n </pre>\n <p>\n-Channels combine communication—the exchange of a value—with\n+Unbuffered channels combine communication—the exchange of a value—with\n synchronization—guaranteeing that two calculations (goroutines) are in\n a known state.\n </p>\n@@ -2741,6 +2749,17 @@ of logical CPUs on the local machine.\n Again, this requirement is expected to be retired as the scheduling and run-time improve.\n </p>\n \n+<p>\n+Be sure not to confuse the ideas of concurrency—structuring a program\n+as independently executing components—and parallelism—executing\n+calculations in parallel for efficiency on multiple CPUs.\n+Although the concurrency features of Go can make some problems easy\n+to structure as parallel computations, Go is a concurrent language,\n+not a parallel one, and not all parallelization problems fit Go\'s model.\n+For a discussion of the distinction, see the talk cited in\n+<a href=\"http://blog.golang.org/2013/01/concurrency-is-not-parallelism.html\">this\n+blog post</a>.\n+\n <h3 id=\"leaky_buffer\">A leaky buffer</h3>\n \n <p>\n@@ -2857,7 +2876,7 @@ it is much more informative than the plain\n \n <p>\n When feasible, error strings should identify their origin, such as by having\n-a prefix naming the package that generated the error. For example, in package\n+a prefix naming the operation or package that generated the error. For example, in package\n <code>image</code>, the string representation for a decoding error due to an\n unknown format is \"image: unknown format\".\n </p>\n@@ -2912,9 +2931,7 @@ that in effect creates a run-time error that will stop the program\n (but see the next section). The function takes a single argument\n of arbitrary type—often a string—to be printed as the\n program dies. It\'s also a way to indicate that something impossible has\n-happened, such as exiting an infinite loop. In fact, the compiler\n-recognizes a <code>panic</code> at the end of a function and\n-suppresses the usual check for a <code>return</code> statement.\n+happened, such as exiting an infinite loop.\n </p>\n \n \n@@ -3016,7 +3033,7 @@ With our recovery pattern in place, the <code>do</code>\n function (and anything it calls) can get out of any bad situation\n cleanly by calling <code>panic</code>. We can use that idea to\n simplify error handling in complex software. Let\'s look at an\n-idealized excerpt from the <code>regexp</code> package, which reports\n+idealized version of a <code>regexp</code> package, which reports\n parsing errors by calling <code>panic</code> with a local\n error type. Here\'s the definition of <code>Error</code>,\n an <code>error</code> method, and the <code>Compile</code> function.\n@@ -3057,18 +3074,27 @@ to <code>err</code>, that the problem was a parse error by asserting\n that it has the local type <code>Error</code>.\n If it does not, the type assertion will fail, causing a run-time error\n that continues the stack unwinding as though nothing had interrupted\n-it. This check means that if something unexpected happens, such\n+it.\n+This check means that if something unexpected happens, such\n as an index out of bounds, the code will fail even though we\n are using <code>panic</code> and <code>recover</code> to handle\n-user-triggered errors.\n+parse errors.\n </p>\n \n <p>\n-With error handling in place, the <code>error</code> method\n+With error handling in place, the <code>error</code> method (because it\'s a\n+method bound to a type, it\'s fine, even natural, for it to have the same name\n+as the builtin <code>error</code> type)\n makes it easy to report parse errors without worrying about unwinding\n-the parse stack by hand.\n+the parse stack by hand:\n </p>\n \n+<pre>\n+if pos==0 {\n+ re.error(\"\'*\' illegal at start of expression\")\n+}\n+</pre>\n+\n <p>\n Useful though this pattern is, it should be used only within a package.\n <code>Parse</code> turns its internal <code>panic</code> calls into\n```
## コアとなるコードの解説
* **`range`と`rune`の拡張**:
* `range`が文字列をUTF-8で解析し、個々のUnicodeコードポイント(`rune`)を生成するという説明が追加されました。これにより、Goが多言語対応においてどのように文字列を扱うかが明確になります。
* `rune`がGoにおけるUnicodeコードポイントの用語であることが明記され、言語仕様へのリンクが提供されました。これは、Goの文字列処理の基礎を理解する上で不可欠な情報です。
* **`fmt.Fprint`の説明の改善**:
* `fmt.Fprint`が`io.Writer`インターフェースを実装する任意のオブジェクトを最初の引数として受け取るという説明が、より直接的で自己完結的な表現に修正されました。
* **`%q`書式指定子の拡張**:
* `%q`が文字列やバイトスライスだけでなく、整数や`rune`にも適用され、単一引用符で囲まれた`rune`定数として出力されることが追記されました。これにより、`%q`の多様な使用法が示され、開発者がより柔軟に書式設定を行えるようになります。
* **`append`関数のシグネチャのHTML修正**:
* `append`関数のHTML表示における型プレースホルダーの書式が修正されました。これは、ドキュメントの正確性と読みやすさを向上させるための細かな修正です。
* **初期化と定数の説明の精度向上**:
* 初期化に関する記述が、異なるパッケージ間のオブジェクトの初期化順序の問題をより正確に表現するように変更されました。
* 定数として利用可能な型に「文字(`rune`)」が追加され、Goの定数の定義範囲が明確になりました。
* **`String`メソッドとレシーバの汎用性の強調**:
* `String`メソッドを任意のユーザー定義型にアタッチできる能力が強調され、`ByteSize`のようなスカラー型にも適用できることが明記されました。これにより、開発者はカスタム型に対して自動的な書式設定をより広範に適用できることを理解できます。
* メソッドがポインタやインターフェース以外の任意の名前付き型に定義できるという点が、`ByteSize`の例を引用して再確認されました。
* **`bytes.Buffer`の説明の正確化**:
* `bytes.Buffer`が`Write`をバイトスライスに適用するというアイデアの「実装」ではなく「中心」であるという表現に修正されました。これは、`bytes.Buffer`が`io.Writer`インターフェースを実装し、その機能の中心にバイトスライスへの書き込みがあることをより正確に示しています。
* **`os.Args`出力例の簡素化**:
* `ArgServer`関数の例で、`os.Args`スライスをループで回して個々の引数を出力する代わりに、`fmt.Println(os.Args)`や`fmt.Fprintln(w, os.Args)`を使ってスライス全体を直接出力するように変更されました。これは、`fmt`パッケージがスライスを適切に書式設定して出力できることを示しており、コードの簡潔化とGoのイディオムに沿った記述を促進します。
* **埋め込みフィールドのアクセスと初期化の明確化**:
* `Job`構造体内の`Logger`埋め込みフィールドの初期化方法が、コンストラクタ内でどのように行われるか具体的に示されました。
* 埋め込みフィールドへのアクセス(例:`job.Logger`)が、そのフィールドのメソッドを洗練させる場合に有用であるという説明が追加されました。これにより、埋め込みフィールドの利用シナリオがより明確になります。
* **チャネルの参照セマンティクスとバッファなしチャネルの同期性の強調**:
* `make`でチャネルを割り当てると、結果の値が基になるデータ構造への参照として機能するという説明が追加されました。これは、チャネルが参照型であるというGoの重要な概念を補強します。
* バッファなしチャネルが「通信と同期を組み合わせる」という点が強調され、その同期的な性質がより明確に説明されました。これは、デッドロックを避けるためにも重要な理解です。
* **並行性 vs. 並列性の区別の追加**:
* 並行性(Concurrency)と並列性(Parallelism)の概念的な違いを明確に説明する新しい段落が追加されました。Goが並行言語であり、並列言語ではないこと、そしてGoの並行性機能が一部の並列計算問題を構造化しやすくする一方で、すべての並列化問題がGoのモデルに適合するわけではないことが述べられています。この区別に関するブログ記事へのリンクも提供され、読者の理解を深めるための重要なリソースが示されました。これは、Goの設計思想と利用範囲を理解する上で非常に重要な追加です。
* **エラー文字列のプレフィックスの柔軟性**:
* エラー文字列が「エラーを生成したパッケージ名をプレフィックスとして持つ」という説明が、「操作またはパッケージ名をプレフィックスとして持つ」に変更されました。これにより、エラーメッセージの命名規則に柔軟性がもたらされ、より具体的なコンテキストを示すことができるようになりました。
* **`panic`と`recover`の挙動の修正と例の追加**:
* コンパイラが関数の終わりでの`panic`を認識し、`return`ステートメントの通常のチェックを抑制するという記述が削除されました。これは、以前のドキュメントの誤解を招く可能性のある記述を修正したものです。
* `panic`と`recover`を用いた`regexp`パッケージの例において、型アサーションがどのように機能し、予期せぬエラー(例:インデックス範囲外)が発生した場合にスタックの巻き戻しが継続されるかがより詳細に説明されました。
* `re.error("'*' illegal at start of expression")`という具体的なコード例が追加され、`error`メソッドの利用方法が視覚的に示されました。これにより、`panic`と`recover`を用いたエラーハンドリングのパターンがより明確に理解できるようになりました。
これらの変更は、Go言語のドキュメントの品質を向上させ、開発者がGoの機能とイディオムをより深く理解するのに役立ちます。
## 関連リンク
* Go言語の公式ドキュメント「Effective Go」: [https://go.dev/doc/effective_go](https://go.dev/doc/effective_go) (このコミットが修正しているドキュメントの最新版)
* Go言語の仕様: [https://go.dev/ref/spec](https://go.dev/ref/spec) (特に`rune`リテラルに関するセクション)
* Goブログ記事「Concurrency is not Parallelism」: [https://go.dev/blog/2013/01/concurrency-is-not-parallelism.html](https://go.dev/blog/2013/01/concurrency-is-not-parallelism.html) (並行性と並列性の区別に関する詳細な議論)
## 参考にした情報源リンク
* GitHubのコミットページ: [https://github.com/golang/go/commit/5f07125cb9333e002a7ddd99a37c1db7645ebd9b](https://github.com/golang/go/commit/5f07125cb9333e002a7ddd99a37c1db7645ebd9b)
* Go言語のドキュメント: [https://go.dev/doc/](https://go.dev/doc/)
* Go言語のブログ: [https://go.dev/blog/](https://go.dev/blog/)
* Go言語の`fmt`パッケージドキュメント: [https://pkg.go.dev/fmt](https://pkg.go.dev/fmt)
* Go言語の`bytes`パッケージドキュメント: [https://pkg.go.dev/bytes](https://pkg.go.dev/bytes)
* Go言語の`os`パッケージドキュメント: [https://pkg.go.dev/os](https://pkg.go.dev/os)
* Go言語の`log`パッケージドキュメント: [https://pkg.go.dev/log](https://pkg.go.dev/log)
* Go言語の`net/http`パッケージドキュメント: [https://pkg.go.dev/net/http](https://pkg.go.dev/net/http)
* Go言語の`regexp`パッケージドキュメント: [https://pkg.go.dev/regexp](https://pkg.go.dev/regexp)