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

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

このコミットは、Go言語の仕様書(doc/go_spec.html)におけるチャネルに関する記述の複数の明確化を目的としています。言語の動作自体を変更するものではなく、既存のチャネルのセマンティクスに関する説明をより正確で理解しやすいものに修正しています。特に、チャネルが複数のゴルーチン間で利用可能であること、値の受け渡しに関する用語の統一、構文定義の対称性の改善、バッファなしチャネルとバッファありチャネルの説明順序の変更、そして「カンマOK」形式での受信値の意味の明確化が含まれます。

コミット

  • コミットハッシュ: 97aa90d251f6f2a951d01b7d1033bc7a42bf6f69
  • Author: Robert Griesemer gri@golang.org
  • Date: Wed May 7 10:40:39 2014 -0700

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

https://github.com/golang/go/commit/97aa90d251f6f2a951d01b7d1033bc7a42bf6f69

元コミット内容

spec: several clarifications to language on channels

- A channel may be used between any number of goroutines,
  not just two.
- Replace "passing a value" (which is not further defined)
  by "sending and receiving a value".
- Made syntax production more symmetric.
- Talk about unbuffered channels before buffered channels.
- Clarify what the comma,ok receive values mean (issue 7785).

Not a language change.

Fixes #7785.

LGTM=rsc, r, iant
R=r, rsc, iant, ken
CC=golang-codereviews
https://golang.org/cl/94030045

変更の背景

Go言語のチャネルは、並行処理におけるゴルーチン間の安全な通信と同期のための強力なプリミティブです。しかし、その仕様書における初期の記述には、一部曖昧さや誤解を招く可能性のある表現が含まれていました。このコミットは、以下の点を背景として、仕様書の記述をより正確かつ明確にするために行われました。

  1. 誤解の解消:
    • 初期の記述では、チャネルが「2つのゴルーチン間」でのみ使用されるかのように読める箇所がありましたが、実際には任意の数のゴルーチンがチャネルを介して通信できます。この誤解を解消する必要がありました。
    • 「値を渡す (passing a value)」という表現が使われていましたが、これはGoのチャネル操作の正確なセマンティクス(送信と受信)を十分に反映していませんでした。
  2. 用語の統一と明確化:
    • チャネルの操作を「送信 (sending)」と「受信 (receiving)」という明確な用語で統一し、曖昧さを排除する必要がありました。
    • チャネルの構文定義(EBNF)が、その使用方法と完全に一致していない部分があり、より対称的で直感的な表現に修正する必要がありました。
  3. 説明の順序の改善:
    • バッファなしチャネルはGoのチャネルの最も基本的な形態であり、同期的な通信を保証します。仕様書の説明において、この基本的な概念をバッファありチャネルよりも先に説明することで、読者の理解を深める狙いがありました。
  4. 「カンマOK」イディオムの明確化:
    • チャネルからの受信操作における「カンマOK」イディオム(value, ok := <-ch)は、チャネルが閉じられたかどうかを判断するために非常に重要です。しかし、okfalseになる具体的な条件(チャネルが閉じられ、かつ送信された値が全て受信された後)について、仕様書での記述が不十分でした。これはGoのIssue #7785で報告されており、このコミットでその点が修正されました。

これらの変更は、Go言語の仕様書をより堅牢で、開発者にとって誤解の少ないものにすることを目的としています。

前提知識の解説

このコミットの変更内容を理解するためには、Go言語の以下の基本的な概念を理解しておく必要があります。

  1. ゴルーチン (Goroutines):

    • Go言語における軽量な並行実行単位です。OSのスレッドよりもはるかに軽量で、数千、数万のゴルーチンを同時に実行することが可能です。goキーワードを使って関数呼び出しの前に記述することで、その関数を新しいゴルーチンとして実行します。
    • ゴルーチンは同じアドレス空間を共有しますが、直接メモリを共有するのではなく、チャネルを介して通信することが推奨されます("Don't communicate by sharing memory; share memory by communicating.")。
  2. チャネル (Channels):

    • ゴルーチン間で値を安全に受け渡しするための通信メカニズムです。チャネルは型付けされており、特定の型の値のみを送信・受信できます。
    • チャネルは、通信だけでなく、ゴルーチン間の同期にも使用されます。
    • チャネルの方向:
      • chan T: 送受信可能な双方向チャネル。
      • chan <- T: 送信専用チャネル。
      • <- chan T: 受信専用チャネル。
      • チャネルは、代入や関数引数として渡す際に、より制限された方向のチャネル型に変換(ダウンキャスト)できます。
    • バッファなしチャネル (Unbuffered Channels):
      • make(chan T) のように容量を指定せずに作成されたチャネルです。
      • 送信操作は、受信側が準備できるまでブロックします。
      • 受信操作は、送信側が準備できるまでブロックします。
      • 送信と受信が同時に行われる「同期」を意味します。
    • バッファありチャネル (Buffered Channels):
      • make(chan T, capacity) のように容量を指定して作成されたチャネルです。capacityはチャネルが保持できる要素の最大数です。
      • 送信操作は、バッファが満杯でない限りブロックしません。バッファが満杯の場合のみブロックします。
      • 受信操作は、バッファが空でない限りブロックしません。バッファが空の場合のみブロックします。
      • バッファのサイズによって、非同期的な通信が可能になります。
  3. チャネル操作:

    • 送信 (Send): ch <- value の形式で、valueをチャネルchに送信します。
    • 受信 (Receive): value := <-ch または <-ch の形式で、チャネルchから値を受信します。
    • close関数: close(ch) を呼び出すことでチャネルを閉じることができます。閉じられたチャネルへの送信はパニックを引き起こしますが、受信は可能です。閉じられたチャネルから値を受信し続けると、最終的にそのチャネルの要素型のゼロ値が返されます。
  4. 「カンマOK」イディオム (Comma-ok Idiom):

    • Go言語では、特定の操作(マップからの読み取り、型アサーション、チャネルからの受信)が2つの値を返すことがあります。2番目の値は通常ブール値で、操作が成功したか、または値が存在したかを示します。
    • チャネルからの受信の場合: value, ok := <-ch
      • oktrueの場合: チャネルから有効な値valueが正常に受信されました。
      • okfalseの場合: チャネルは閉じられており、valueはチャネルの要素型のゼロ値です。これは、チャネルが閉じられた後に、それまでに送信された全ての値が受信され尽くしたことを意味します。
  5. make関数:

    • スライス、マップ、チャネルといった組み込みの参照型を初期化するために使用される組み込み関数です。チャネルの場合、make(chan T, capacity) の形式でチャネルを作成します。

技術的詳細

このコミットは、Go言語の仕様書(doc/go_spec.html)内のチャネルに関する記述を、より正確で誤解の少ないものにするための複数の修正を含んでいます。以下に、それぞれの変更点の技術的な詳細を解説します。

  1. 「チャネルは任意の数のゴルーチン間で利用可能」の明確化:

    • 変更前: 「チャネルは、2つの並行して実行される関数が実行を同期し、指定された要素型の値を渡すことで通信するためのメカニズムを提供します。」
    • 変更後: 「チャネルは、並行して実行される関数が、指定された要素型の値を送信および受信することで通信するためのメカニズムを提供します。」さらに、「単一のチャネルは、追加の同期なしに、任意の数のゴルーチンによって送信ステートメント、受信操作、および組み込み関数caplenの呼び出しで使用できます。」という文が追加されました。
    • 技術的意味: これは、チャネルが単なる2者間の通信手段ではなく、多対多の通信パターンを安全にサポートする設計であることを明確にしています。Goのチャネルは内部的にミューテックスなどの同期プリミティブを使用して競合状態を防いでいるため、複数の送信者と複数の受信者が同時にチャネルを操作してもデータ競合は発生しません。この明確化により、開発者がチャネルの利用範囲を誤解する可能性が低減されます。
  2. 「値を渡す」から「値を送信および受信する」への置換:

    • 変更前: 「値を渡す (passing a value)」
    • 変更後: 「値を送信 (sending) および受信 (receiving) する」
    • 技術的意味: 「値を渡す」という表現は、関数引数や戻り値のように、値が一方的に移動するような印象を与える可能性があります。しかし、チャネルにおける通信は、送信側と受信側の両方が関与する双方向のプロセスです。この変更により、チャネル操作の正確なセマンティクスがより明確に伝わるようになりました。これは、GoのCSP(Communicating Sequential Processes)モデルにおける通信の概念をより忠実に反映しています。
  3. 構文定義の対称性の改善:

    • 変更前: ChannelType = ( "chan" [ "<-" ] | "<-" "chan" ) ElementType .
    • 変更後: ChannelType = ( "chan" | "chan" "<-" | "<-" "chan" ) ElementType .
    • 技術的意味: 変更前は、chanの後に<-が続く形式と、<-の後にchanが続く形式が並列に記述されていましたが、chan単独の形式が欠落していました。変更後は、chan(双方向)、chan <-(送信専用)、<- chan(受信専用)の3つの主要な形式がより対称的かつ網羅的に表現されています。これは、Goのチャネル型の定義がより直感的で完全なものになったことを意味します。
  4. バッファなしチャネルの説明をバッファありチャネルの前に配置:

    • 変更前: バッファありチャネルの説明が先にあり、その後にバッファなしチャネルが説明されていました。
    • 変更後: 「容量がゼロまたは存在しない場合、チャネルはバッファなしであり、送信者と受信者の両方が準備できた場合にのみ通信が成功します。それ以外の場合、チャネルはバッファありであり、バッファが満杯でない(送信)または空でない(受信)限り、通信操作はブロックせずに成功します。」というように、バッファなしチャネルの説明が先に記述されるようになりました。
    • 技術的意味: バッファなしチャネルは、Goのチャネルの最も基本的な同期メカニズムを体現しています。送信と受信が同時に行われる「ランデブー」ポイントを提供します。この変更は、仕様書を読む人がまずこの基本的な同期モデルを理解し、その後にバッファリングによる非同期動作の概念に進むことで、より段階的かつ論理的な学習パスを提供します。
  5. 「カンマOK」受信値の意味の明確化 (Issue #7785):

    • 変更前: 「closeされたチャネルからの受信操作は常に即座に進行し、要素型のゼロ値を返します。」
    • 変更後: 「closeされたチャネルからの受信操作は常に即座に進行し、以前に送信された値がすべて受信された後に、要素型のゼロ値を返します。」
    • 技術的意味: これは非常に重要な明確化です。value, ok := <-ch の形式でチャネルから受信する際、okfalseになるのは、単にチャネルが閉じられたからではありません。チャネルが閉じられた後でも、バッファにまだ値が残っている場合、それらの値はoktrueの状態で受信され続けます。okfalseになるのは、チャネルが閉じられ、かつバッファ内の全ての値が消費され尽くした後、つまりチャネルが完全に空になった後です。この明確化により、開発者はチャネルのクローズと受信の挙動を正確に理解し、チャネルを介した安全なシャットダウンロジックをより堅牢に実装できるようになります。
  6. make関数によるチャネル作成の記述の明確化:

    • 変更前:
      • make(T) channel synchronous channel of type T
      • make(T, n) channel asynchronous channel of type T, buffer size n
    • 変更後:
      • make(T) channel unbuffered channel of type T
      • make(T, n) channel buffered channel of type T, buffer size n
    • 技術的意味: 「synchronous channel」と「asynchronous channel」という用語は、Goのチャネルの動作を説明する上で正確ではありますが、より直接的に「unbuffered channel」と「buffered channel」という用語を使用することで、チャネルの作成方法とバッファリングの有無との直接的な関連性が明確になります。これは、Goコミュニティで一般的に使用される用語との整合性も高めます。

これらの変更は、Go言語のチャネルのセマンティクス自体を変更するものではなく、その仕様書における記述の精度と理解度を向上させることを目的としています。

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

このコミットは、Go言語の仕様書を記述しているHTMLファイル doc/go_spec.html のみを変更しています。

diff --git a/doc/go_spec.html b/doc/go_spec.html
index 114ceed86f..2f6fd2b97e 100644
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1278,20 +1278,23 @@ may be added.
 <h3 id=\"Channel_types\">Channel types</h3>
 
 <p>
-A channel provides a mechanism for two concurrently executing functions
-to synchronize execution and communicate by passing a value of a
-specified element type.
+A channel provides a mechanism for
+<a href=\"#Go_statements\">concurrently executing functions</a>
+to communicate by
+<a href=\"#Send_statements\">sending</a> and
+<a href=\"#Receive_operator\">receiving</a>
+values of a specified element type.
 The value of an uninitialized channel is <code>nil</code>.
 </p>
 
 <pre class=\"ebnf\">
-ChannelType = ( \"chan\" [ \"<-\" ] | \"<-\" \"chan\" ) ElementType .
+ChannelType = ( \"chan\" | \"chan\" \"<-\" | \"<-\" \"chan\" ) ElementType .
 </pre>
 
 <p>
-The <code><-</code> operator specifies the channel <i>direction</i>,
+The optional <code><-</code> operator specifies the channel <i>direction</i>,
 <i>send</i> or <i>receive</i>. If no direction is given, the channel is
-<i>bi-directional</i>.
+<i>bidirectional</i>.
 A channel may be constrained only to send or only to receive by
 <a href=\"#Conversions\">conversion</a> or <a href=\"#Assignments\">assignment</a>.
 </p>
@@ -1318,7 +1321,7 @@ chan (&lt;-chan int)\n A new, initialized channel\n value can be made using the built-in function\n <a href=\"#Making_slices_maps_and_channels\"><code>make</code></a>,\n-which takes the channel type and an optional capacity as arguments:\n+which takes the channel type and an optional <i>capacity</i> as arguments:\n </p>\n \n <pre>\n@@ -1326,21 +1329,35 @@ make(chan int, 100)\n </pre>\n \n <p>\n-The capacity, in number of elements, sets the size of the buffer in the channel. If the\n-capacity is greater than zero, the channel is asynchronous: communication operations\n-succeed without blocking if the buffer is not full (sends) or not empty (receives),\n-and elements are received in the order they are sent.\n-If the capacity is zero or absent, the communication succeeds only when both a sender and\n-receiver are ready.\n+The capacity, in number of elements, sets the size of the buffer in the channel.\n+If the capacity is zero or absent, the channel is unbuffered and communication\n+succeeds only when both a sender and receiver are ready. Otherwise, the channel is\n+buffered and communication operations succeed without blocking if the buffer\n+is not full (sends) or not empty (receives).\n A <code>nil</code> channel is never ready for communication.\n </p>\n \n <p>\n A channel may be closed with the built-in function\n-<a href=\"#Close\"><code>close</code></a>; the\n-multi-valued assignment form of the\n+<a href=\"#Close\"><code>close</code></a>.\n+The multi-valued assignment form of the\n <a href=\"#Receive_operator\">receive operator</a>\n-tests whether a channel has been closed.\n+reports whether a received value was sent before\n+the channel was closed.\n+</p>\n+\n+<p>\n+A single channel may be used in\n+<a href=\"#Send_statements\">send statements</a>,\n+<a href=\"#Receive_operator\">receive operations</a>,\n+and calls to the built-in functions\n+<a href=\"#Length_and_capacity\"><code>cap</code></a> and\n+<a href=\"#Length_and_capacity\"><code>len</code></a>\n+by any number of goroutines without further synchronization.\n+Channels act as first-in-first-out queues.\n+For example, if one goroutine sends values on a channel\n+and a second goroutine receives them, the values are\n+received in the order sent.\n </p>\n \n <h2 id=\"Properties_of_types_and_values\">Properties of types and values</h2>\n@@ -3389,7 +3406,8 @@ and the type of the receive operation is the element type of the channel.\n The expression blocks until a value is available.\n Receiving from a <code>nil</code> channel blocks forever.\n A receive operation on a <a href=\"#Close\">closed</a> channel can always proceed\n-immediately, yielding the element type\'s <a href=\"#The_zero_value\">zero value</a>.\n+immediately, yielding the element type\'s <a href=\"#The_zero_value\">zero value</a>\n+after any previously sent values have been received.\n </p>\n \n <pre>\n@@ -4238,22 +4256,8 @@ A send on a closed channel proceeds by causing a <a href=\"#Run_time_panics\">run-\n A send on a <code>nil</code> channel blocks forever.\n </p>\n \n-<p>\n-Channels act as first-in-first-out queues.\n-For example, if a single goroutine sends on a channel values\n-that are received by a single goroutine, the values are received in the order sent.\n-</p>\n-\n-<p>\n-A single channel may be used for send and receive\n-operations and calls to the built-in functions\n-<a href=\"#Length_and_capacity\"><code>cap</code></a> and\n-<a href=\"#Length_and_capacity\"><code>len</code></a>\n-by any number of goroutines without further synchronization.\n-</p>\n-\n <pre>\n-ch <- 3\n+ch <- 3  // send value 3 to channel ch\n </pre>\n \n \n@@ -5383,8 +5387,8 @@ make(T, n, m)    slice      slice of type T with length n and capacity m\n make(T)          map        map of type T\n make(T, n)       map        map of type T with initial space for n elements\n \n-make(T)          channel    synchronous channel of type T\n-make(T, n)       channel    asynchronous channel of type T, buffer size n\n+make(T)          channel    unbuffered channel of type T\n+make(T, n)       channel    buffered channel of type T, buffer size n\n </pre>\n \n \n```

## コアとなるコードの解説

上記の差分は、Go言語の公式仕様書である `doc/go_spec.html` に対する変更を示しています。以下に、各変更箇所の詳細な解説を行います。

1.  **チャネルの利用に関する記述の修正 (L1280-1285)**:
    *   **変更前**: 「チャネルは、2つの並行して実行される関数が実行を同期し、指定された要素型の値を渡すことで通信するためのメカニズムを提供します。」
    *   **変更後**: 「チャネルは、並行して実行される関数が、指定された要素型の値を**送信**および**受信**することで通信するためのメカニズムを提供します。」
    *   **解説**: 「2つの」という限定的な表現が削除され、より一般的な「並行して実行される関数」に修正されました。また、「値を渡す (passing a value)」という曖昧な表現が、Goのチャネル操作の正確な用語である「送信 (sending)」と「受信 (receiving)」に置き換えられました。これにより、チャネルが多対多の通信にも利用できること、およびその操作のセマンティクスが明確になりました。

2.  **`ChannelType` EBNF構文の修正 (L1289)**:
    *   **変更前**: `ChannelType = ( "chan" [ "<-" ] | "<-" "chan" ) ElementType .`
    *   **変更後**: `ChannelType = ( "chan" | "chan" "<-" | "<-" "chan" ) ElementType .`
    *   **解説**: 変更前は、双方向チャネルの最も基本的な形式である `chan T` が明示的に含まれていませんでした。変更後は、`"chan"`(双方向)、`"chan" "<-"`(送信専用)、`"<-" "chan"`(受信専用)の3つの主要なチャネル型定義が対称的に並べられ、構文の完全性と直感性が向上しました。

3.  **チャネル方向指定子に関する記述の修正 (L1293)**:
    *   **変更前**: 「`<-`演算子はチャネルの*方向*、*送信*または*受信*を指定します。」
    *   **変更後**: 「オプションの`<-`演算子はチャネルの*方向*、*送信*または*受信*を指定します。」
    *   **解説**: `<-`演算子が「オプション」であることが明示されました。これは、`chan T`のように方向指定子がない場合に双方向チャネルとなることをより明確に示しています。

4.  **`make`関数における容量引数の記述の修正 (L1321)**:
    *   **変更前**: 「チャネル型とオプションの容量を引数として取ります。」
    *   **変更後**: 「チャネル型とオプションの*容量*を引数として取ります。」
    *   **解説**: 「容量」という単語がイタリック体になり、より強調されるようになりました。これは、チャネルのバッファリング挙動を決定する重要な概念であることを示唆しています。

5.  **バッファなしチャネルとバッファありチャネルの説明順序の変更と明確化 (L1329-1336)**:
    *   **変更前**: バッファありチャネル(非同期チャネル)の説明が先にあり、その後にバッファなしチャネル(容量ゼロまたはなし)の説明がありました。
    *   **変更後**: 「容量がゼロまたは存在しない場合、チャネルは**バッファなし**であり、送信者と受信者の両方が準備できた場合にのみ通信が成功します。それ以外の場合、チャネルは**バッファあり**であり、バッファが満杯でない(送信)または空でない(受信)限り、通信操作はブロックせずに成功します。」
    *   **解説**: バッファなしチャネルの説明がバッファありチャネルの前に来るように順序が変更されました。これにより、Goのチャネルの最も基本的な同期モデルが最初に提示され、その後にバッファリングによる非同期動作が説明されることで、読者の理解が深まるように改善されました。

6.  **チャネルのクローズと「カンマOK」受信の明確化 (L1340-1345)**:
    *   **変更前**: 「`close`関数でチャネルを閉じることができます。受信演算子の多値代入形式は、チャネルが閉じられたかどうかをテストします。」
    *   **変更後**: 「`close`関数でチャネルを閉じることができます。受信演算子の多値代入形式は、受信された値がチャネルが閉じられる前に送信されたものかどうかを報告します。」
    *   **解説**: `ok`値が単にチャネルが閉じられたことを示すだけでなく、「受信された値がチャネルが閉じられる前に送信されたものかどうか」を報告するという、より正確な意味合いが記述されました。これは、チャネルが閉じられた後でも、バッファに残っている値は`ok=true`で受信されるという重要なセマンティクスを反映しています。

7.  **複数のゴルーチンによるチャネル利用の明確化とFIFOの保証 (L1347-1358)**:
    *   **追加された段落**: 「単一のチャネルは、送信ステートメント、受信操作、および組み込み関数`cap`と`len`の呼び出しにおいて、追加の同期なしに任意の数のゴルーチンによって使用できます。チャネルは先入れ先出し(FIFO)キューとして機能します。例えば、あるゴルーチンがチャネルに値を送信し、別のゴルーチンがそれらを受信する場合、値は送信された順序で受信されます。」
    *   **解説**: この新しい段落は、チャネルが複数のゴルーチン間で安全に共有できること、そしてチャネルが本質的にFIFO(First-In, First-Out)の順序を保証することを明確にしています。これは、Goのチャネルの重要な特性であり、並行プログラムの予測可能性と信頼性を高めます。

8.  **クローズされたチャネルからの受信に関する明確化 (L3392-3393)**:
    *   **変更前**: 「`close`されたチャネルからの受信操作は常に即座に進行し、要素型のゼロ値を返します。」
    *   **変更後**: 「`close`されたチャネルからの受信操作は常に即座に進行し、**以前に送信された値がすべて受信された後**に、要素型のゼロ値を返します。」
    *   **解説**: これは、Issue #7785で指摘された「カンマOK」イディオムの挙動に関する最も重要な明確化です。`ok`が`false`になるのは、チャネルが閉じられただけでなく、そのチャネルのバッファにまだ残っていた全ての値が消費され尽くした後であることを明示しています。これにより、開発者はチャネルのクローズと値の受信のタイミングをより正確に理解し、デッドロックや予期せぬゼロ値の受信を防ぐためのロジックを適切に実装できます。

9.  **冗長な段落の削除 (L4240-4261)**:
    *   **削除された段落**: 以前は、チャネルがFIFOキューとして機能することや、複数のゴルーチンによって使用できることに関する記述が、このコミットで追加された新しい段落と重複していたため削除されました。
    *   **解説**: 情報の重複を避け、仕様書全体の整合性と簡潔性を保つための整理です。

10. **`make`関数によるチャネル作成の用語の統一 (L5386-5387)**:
    *   **変更前**:
        *   `make(T)` channel synchronous channel of type T
        *   `make(T, n)` channel asynchronous channel of type T, buffer size n
    *   **変更後**:
        *   `make(T)` channel unbuffered channel of type T
        *   `make(T, n)` channel buffered channel of type T, buffer size n
    *   **解説**: 「synchronous channel」と「asynchronous channel」という用語が、より一般的で直接的な「unbuffered channel」と「buffered channel」に置き換えられました。これにより、チャネルのバッファリング挙動と作成方法との関連性がより明確になり、Goコミュニティで広く使われている用語との整合性が高まりました。

これらの変更は、Go言語のチャネルのセマンティクス自体を変更するものではなく、その仕様書における記述の精度と理解度を向上させることを目的としています。

## 関連リンク

*   GitHubコミットページ: [https://github.com/golang/go/commit/97aa90d251f6f2a951d01b7d1033bc7a42bf6f69](https://github.com/golang/go/commit/97aa90d251f6f2a951d01b7d1033bc7a42bf6f69)
*   Go Issue #7785 (このコミットで修正された問題): 関連するGoのIssueトラッカー上の議論は、このコミットの時点では存在していたものの、現在の公開情報からは直接参照できない可能性があります。しかし、コミットメッセージに明記されている通り、「カンマOK」受信値の意味の明確化がこのIssueによって促されました。
*   Go Code Review (CL 94030045): [https://golang.org/cl/94030045](https://golang.org/cl/94030045)

## 参考にした情報源リンク

*   Go言語公式仕様書: [https://go.dev/ref/spec](https://go.dev/ref/spec) (このコミットが変更を加えたドキュメントの最新版)
*   Go言語のチャネルに関する公式ブログ記事やドキュメント (一般的なチャネルの理解のため)
    *   A Tour of Go - Concurrency: [https://go.dev/tour/concurrency/1](https://go.dev/tour/concurrency/1)
    *   Go Concurrency Patterns: Pipelines and Cancellation: [https://go.dev/blog/pipelines](https://go.dev/blog/pipelines)
    *   Effective Go - Concurrency: [https://go.dev/doc/effective_go#concurrency](https://go.dev/doc/effective_go#concurrency)
*   Go言語における「カンマOK」イディオムに関する一般的な解説記事 (例: Medium, freeCodeCampなど)
    *   Go: The comma ok idiom: [https://medium.com/@ankur_anand/go-the-comma-ok-idiom-e6f72322274d](https://medium.com/@ankur_anand/go-the-comma-ok-idiom-e6f72322274d)
    *   Understanding the Comma Ok Idiom in Go: [https://www.freecodecamp.org/news/understanding-the-comma-ok-idiom-in-go/](https://www.freecodecamp.org/news/understanding-the-comma-ok-idiom-in-go/)