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

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

このコミットは、Go言語の仕様書(The Go Programming Language Specification)において、breakcontinue、およびgotoステートメントの動作が関数境界を越えて適用されないことを明確にするための変更です。特に、これらの制御フロー文が常に同じ関数内で機能することを強調し、誤解の余地をなくすことを目的としています。

コミット

  • コミットハッシュ: 94849d5a78009dcaafbde2847cc0a27f53aa3723
  • Author: Robert Griesemer gri@golang.org
  • Date: Wed May 28 08:43:47 2014 -0700

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

https://github.com/golang/go/commit/94849d5a78009dcaafbde2847cc0a27f53aa3723

元コミット内容

spec: clarify that break/continue do not work across function boundaries

Also made it extra clear for goto statements (even though label scopes
are already limited to the function defining a label).

Fixes #8040.

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

変更の背景

Go言語の初期の仕様書では、breakcontinuegotoといった制御フロー文の適用範囲について、関数境界との関係が明示的に記述されていない部分がありました。これにより、これらのステートメントが関数スコープを超えて影響を及ぼす可能性があるという誤解が生じる可能性がありました。

特に、breakcontinueはループやswitchselectステートメントの実行を制御しますが、これらがネストされた関数呼び出しの内部から外側の関数にあるループなどを制御できるのか、という疑問が生じることがありました。同様に、gotoステートメントもラベルへのジャンプを伴いますが、そのラベルが別の関数内に存在する場合にどうなるのか、という点が不明瞭でした。

このコミットは、このような曖昧さを解消し、Go言語の設計思想(制御フローは常にローカルなスコープに限定される)を明確に反映させるために行われました。これにより、開発者がGoコードの動作をより正確に理解し、予期せぬ挙動を避けることができるようになります。Fixes #8040という記述から、この変更が特定の報告された問題や議論に対応するものであることが示唆されますが、具体的な問題内容はコミットメッセージからは読み取れません。しかし、仕様の明確化が目的であることは明らかです。

前提知識の解説

このコミットの理解には、以下のGo言語の基本的な概念と制御フロー文に関する知識が必要です。

  1. 関数 (Functions): Go言語におけるコードの基本的な実行単位です。各関数は独自のスコープを持ち、その中で宣言された変数やラベルは通常、その関数内でのみ有効です。
  2. break ステートメント:
    • for ループ、switch ステートメント、select ステートメントの実行を即座に終了させ、それらのステートメントの直後のコードに制御を移します。
    • ラベル付きbreakを使用すると、ネストされたループやswitch/selectの特定の外側のステートメントを終了させることができます。
  3. continue ステートメント:
    • for ループの現在のイテレーションをスキップし、次のイテレーションを開始します。
    • ラベル付きcontinueを使用すると、ネストされたループの特定の外側のループの次のイテレーションを開始できます。
  4. goto ステートメント:
    • プログラムの実行フローを、指定されたラベルが付いたステートメントに無条件にジャンプさせます。
    • gotoの利用は、コードの可読性を損なう可能性があるため、一般的には推奨されません。
  5. スコープ (Scope): プログラム内で識別子(変数、関数、ラベルなど)が参照可能である領域を指します。Go言語では、識別子のスコープは通常、それらが宣言されたブロックや関数に限定されます。

このコミットの核心は、これらの制御フロー文が「関数スコープ」という境界を越えて作用することはない、というGo言語の設計原則を仕様書に明記することにあります。つまり、ある関数内でbreakcontinuegotoを使用しても、それが呼び出し元の関数や別の関数内の構造に影響を与えることはありません。

技術的詳細

このコミットは、Go言語の仕様書であるdoc/go_spec.htmlファイルを直接修正することで、制御フロー文のセマンティクスを明確にしています。具体的な変更は、breakcontinuegotoの各ステートメントの説明に「同じ関数内(within the same function)」という文言を追加することです。

  • breakステートメント: 以前の記述では、breakforswitchselectステートメントを終了させるとだけ書かれていましたが、これに「同じ関数内にある」という条件が追加されました。これにより、関数呼び出しを挟んで外側のループなどをbreakすることはできないことが明確になります。
  • continueステートメント: 同様に、continueforループの次のイテレーションを開始する際に、「そのforループが同じ関数内になければならない」という条件が追加されました。
  • gotoステートメント: gotoがラベルに制御を移す際に、「そのラベルが同じ関数内になければならない」という条件が追加されました。gotoのラベルスコープは元々関数内に限定されていましたが、この変更によりその点がより強調され、誤解の余地がなくなりました。

これらの変更は、Goコンパイラやランタイムの実際の挙動を変更するものではなく、あくまでGo言語の「仕様」をより正確かつ明確に記述するためのものです。Go言語の設計者は、これらの制御フロー文が関数境界を越えて作用しないことを意図しており、このコミットはその意図を公式文書に反映させたものと言えます。これにより、Go言語の学習者や開発者が、言語の挙動についてより正確な理解を持つことができるようになります。

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

変更はdoc/go_spec.htmlファイルに対して行われました。以下に、その差分を示します。

--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,6 +1,6 @@
 <!--{
 	"Title": "The Go Programming Language Specification",
-"	Subtitle": "Version of May 22, 2014",
+"	Subtitle": "Version of May 28, 2014",
 	"Path": "/ref/spec"
 }-->
 
@@ -5093,7 +5093,8 @@ func f(n int) (res int, err error) {
 A "break" statement terminates execution of the innermost
 <a href="#For_statements">"for"</a>,
 <a href="#Switch_statements">"switch"</a>, or
-<a href="#Select_statements">"select"</a> statement.
+<a href="#Select_statements">"select"</a> statement
+within the same function.
 </p>
 
 <pre class="ebnf">
@@ -5127,6 +5128,7 @@ OuterLoop:\n <p>\n A "continue" statement begins the next iteration of the\n innermost <a href="#For_statements">"for" loop</a> at its post statement.\n+The "for" loop must be within the same function.\n </p>\n \n <pre class="ebnf">\n@@ -5154,7 +5156,8 @@ RowLoop:\n <h3 id=\"Goto_statements\">Goto statements</h3>\n \n <p>\n-A "goto" statement transfers control to the statement with the corresponding label.\n+A "goto" statement transfers control to the statement with the corresponding label\n+within the same function.\n </p>\n \n <pre class="ebnf">\n```

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

上記の差分は、Go言語の仕様書における以下の3つのセクションに修正を加えています。

1.  **`break` ステートメントのセクション**:
    *   変更前: `A "break" statement terminates execution of the innermost "for", "switch", or "select" statement.`
    *   変更後: `A "break" statement terminates execution of the innermost "for", "switch", or "select" statement within the same function.`
    *   解説: `break`が適用される`for`、`switch`、`select`ステートメントが、`break`ステートメントと同じ関数内になければならないことを明示しています。これにより、関数呼び出しを介して外側の制御構造を`break`できないことが明確になります。

2.  **`continue` ステートメントのセクション**:
    *   変更前: `A "continue" statement begins the next iteration of the innermost "for" loop at its post statement.`
    *   変更後: `A "continue" statement begins the next iteration of the innermost "for" loop at its post statement. The "for" loop must be within the same function.`
    *   解説: `continue`が適用される`for`ループが、`continue`ステートメントと同じ関数内になければならないことを明確にしています。

3.  **`goto` ステートメントのセクション**:
    *   変更前: `A "goto" statement transfers control to the statement with the corresponding label.`
    *   変更後: `A "goto" statement transfers control to the statement with the corresponding label within the same function.`
    *   解説: `goto`がジャンプする先のラベルが、`goto`ステートメントと同じ関数内になければならないことを明示しています。`goto`のラベルスコープは元々関数内に限定されるため、これは既存の挙動の再確認と強調になります。

これらの変更は、Go言語の制御フローのセマンティクスに関する曖昧さを排除し、仕様書をより正確で理解しやすいものにすることを目的としています。

## 関連リンク

*   GitHubコミットページ: [https://github.com/golang/go/commit/94849d5a78009dcaafbde2847cc0a27f53aa3723](https://github.com/golang/go/commit/94849d5a78009dcaafbde2847cc0a27f53aa3723)
*   Go Code Review (Gerrit) リンク: `https://golang.org/cl/99550043` (これは古いGerritのURL形式であり、現在はGitHubのプルリクエストに統合されていますが、コミットメッセージに記載されているため含めます。)
*   Go Issue #8040: (直接的なGitHub Issueのリンクは見つかりませんでしたが、コミットメッセージに記載されています。)

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

*   The Go Programming Language Specification: [https://go.dev/ref/spec](https://go.dev/ref/spec) (Go言語の公式仕様書)
*   Go言語の公式ドキュメント (break, continue, gotoに関するセクション)