[インデックス 15549] ファイルの概要
このコミットは、Go言語の仕様書(doc/go_spec.html
)におけるfallthrough
ステートメントの記述を修正するものです。具体的には、switch
文の最後のcase
またはdefault
節ではfallthrough
ステートメントを使用できないという制約を明確にし、またfallthrough
がラベルを持つ可能性があることを追記しています。これは、以前の関連する変更(CL 7370053)がfallthrough
をswitch
文の構文の一部として扱おうとしたものの、ラベル付きステートメントとの兼ね合いで仕様の変更が複雑になりすぎたため、その代替として提案されました。この変更はGo言語のIssue #4923を修正します。
コミット
commit 67a6b4f0ef04e547e671230d84f96b00a2966113
Author: Robert Griesemer <gri@golang.org>
Date: Fri Mar 1 16:45:14 2013 -0800
spec: fallthrough may not appear in last clause of a switch
Replacement for CL 7370053 which attempted to make fallthrough's
syntactically a part of switch statements. Because they may be
labeled, fixing that CL completely would require too much spec
surgery.
Fixes #4923.
R=r, iant, rsc, ken
CC=golang-dev
https://golang.org/cl/7416048
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/67a6b4f0ef04e547e671230d84f96b00a2966113
元コミット内容
spec: fallthrough may not appear in last clause of a switch
このコミットは、fallthrough
ステートメントがswitch
文の最後の節に現れてはならないという仕様変更を記述しています。これは、以前の変更(CL 7370053)の代替であり、その変更がfallthrough
をswitch
文の構文の一部にしようとしたものの、fallthrough
がラベルを持つ可能性があるため、仕様の変更が複雑になりすぎたために置き換えられました。このコミットはIssue #4923を修正します。
変更の背景
この変更の背景には、Go言語のswitch
ステートメントにおけるfallthrough
キーワードの振る舞いと、その仕様記述に関する課題がありました。
Goのswitch
ステートメントは、他のC系の言語とは異なり、デフォルトでcase
節の実行後に自動的に次のcase
節に「フォールスルー」しません。各case
節は暗黙的にbreak
を含んでいるかのように振る舞います。しかし、明示的に次のcase
節に制御を移したい場合にfallthrough
キーワードを使用します。
問題は、fallthrough
がswitch
文の最後のcase
節やdefault
節で使用された場合、次に実行すべきcase
節が存在しないため、その振る舞いが未定義または無意味になる点でした。Go言語のIssue #4923は、この曖昧さを解消し、fallthrough
が最後の節で使用された場合にコンパイルエラーとすべきであるという提案でした。
以前、CL 7370053という変更がこの問題に対処しようとしましたが、そのアプローチはfallthrough
をswitch
文の構文規則に直接組み込むものでした。しかし、Go言語ではfallthrough
ステートメントも他のステートメントと同様にラベルを持つことが可能です(例: MyLabel: fallthrough
)。この「ラベル付きfallthrough
」という特性が、fallthrough
をswitch
構文の一部として厳密に定義しようとすると、仕様書全体の「手術」(spec surgery)が必要になるほど複雑な変更を伴うことが判明しました。
そのため、このコミット(CL 7416048)は、以前のCL 7370053の代替として、よりシンプルかつ直接的な方法でこの問題を解決することを目指しました。すなわち、fallthrough
がswitch
の最後の節に現れてはならないという制約を、仕様書のテキスト記述として明確に追加することで、複雑な構文変更を避けるアプローチが取られました。
前提知識の解説
Go言語のswitch
ステートメント
Go言語のswitch
ステートメントは、複数の条件分岐を簡潔に記述するための制御構造です。他のC系の言語(C, C++, Javaなど)とは異なり、Goのswitch
は各case
節の終わりに暗黙的なbreak
を含んでいます。つまり、あるcase
節がマッチして実行された場合、そのcase
節の処理が完了すると、自動的にswitch
ステートメント全体から抜けます。
例:
package main
import "fmt"
func main() {
i := 2
switch i {
case 1:
fmt.Println("one")
case 2:
fmt.Println("two") // ここが実行される
case 3:
fmt.Println("three")
}
// 出力: two
// case 2の実行後、switch文から抜ける
}
fallthrough
キーワード
Go言語で、あるcase
節の実行後に次のcase
節のコードも実行したい場合、明示的にfallthrough
キーワードを使用します。fallthrough
は、そのcase
節の最後のステートメントとして記述され、制御を次のcase
節の最初のステートメントに移します。
例:
package main
import "fmt"
func main() {
i := 2
switch i {
case 1:
fmt.Println("one")
case 2:
fmt.Println("two")
fallthrough // ここで次のcaseにフォールスルー
case 3:
fmt.Println("three") // ここも実行される
case 4:
fmt.Println("four")
}
// 出力:
// two
// three
}
ラベル付きステートメント
Go言語では、for
, switch
, select
などのステートメントや、break
, continue
, goto
などの制御フローキーワードにラベルを付けることができます。ラベルは識別子とコロン(:
)で構成され、ステートメントの前に置かれます。これにより、ネストされたループやswitch
から特定の外側のステートメントに制御を移すことが可能になります。
例:
package main
import "fmt"
func main() {
OuterLoop:
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
if i*j == 4 {
break OuterLoop // OuterLoopを抜ける
}
fmt.Printf("%d,%d ", i, j)
}
}
fmt.Println("\nDone")
}
fallthrough
もステートメントであるため、技術的にはラベルを付けることが可能です(例: MyFallthrough: fallthrough
)。ただし、実用上はあまり一般的ではありません。
技術的詳細
このコミットは、Go言語の仕様書(doc/go_spec.html
)の「Switch statements」セクションと「Fallthrough statements」セクションの記述を更新しています。
主な変更点:
-
switch
ステートメントのセクション (#Expression_switches
):- 変更前:
In a case or default clause, the last statement only may be a "fallthrough" statement... (caseまたはdefault節では、最後のステートメントのみが"fallthrough"ステートメントでありうる...)
- 変更後:
In a case or default clause, the last non-empty statement may be a (possibly labeled) "fallthrough" statement... (caseまたはdefault節では、最後の非空ステートメントは(おそらくラベル付きの)"fallthrough"ステートメントでありうる...) A "fallthrough" statement may appear as the last statement of all but the last clause of an expression switch. (「fallthrough」ステートメントは、式switchの最後の節を除くすべての節の最後のステートメントとして現れることができる。)
この変更により、
fallthrough
が「ラベル付き」である可能性が明示され、さらに重要な点として、「式switch
の最後の節を除くすべての節」でのみfallthrough
が許可されるという新しい制約が追加されました。これにより、fallthrough
が次に続くcase
節を持たない場所で使用されることによる曖昧さが解消されます。 - 変更前:
-
fallthrough
ステートメントのセクション (#Fallthrough_statements
):- 変更前:
It may be used only as the final non-empty statement in a case or default clause in an expression "switch" statement. (それは、式"switch"ステートメントのcaseまたはdefault節における最後の非空ステートメントとしてのみ使用できる。)
- 変更後:
It may be used only as the final non-empty statement in such a clause. (それは、そのような節における最後の非空ステートメントとしてのみ使用できる。)
この変更は、
fallthrough
ステートメントの一般的な説明から、switch
文の最後の節での使用に関する具体的な制約を削除し、その制約はswitch
ステートメントのセクションで一元的に記述されるように整理されました。これにより、仕様の記述がより明確かつ整合的になります。 - 変更前:
このコミットは、Go言語の仕様をより厳密にし、fallthrough
の誤用を防ぐための重要な修正です。特に、fallthrough
がラベルを持つ可能性という既存の言語機能と、switch
文の最後の節でのfallthrough
の禁止という新しい制約を、構文規則の複雑な変更なしに、仕様書のテキスト記述で明確に表現することに成功しています。
コアとなるコードの変更箇所
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,6 +1,6 @@
<!--{
"Title": "The Go Programming Language Specification",
- "Subtitle": "Version of February 11, 2013",
+ "Subtitle": "Version of March 1, 2013",
"Path": "/ref/spec"
}-->
@@ -4154,12 +4154,14 @@ ExprSwitchCase = "case" ExpressionList | "default" .
</pre>
<p>
-In a case or default clause,
-the last statement only may be a "fallthrough" statement
-(§<a href="#Fallthrough_statements">Fallthrough statement</a>) to
+In a case or default clause, the last non-empty statement
+may be a (possibly <a href="#Labeled_statements">labeled</a>)\n+<a href="#Fallthrough_statements">"fallthrough" statement</a> to
indicate that control should flow from the end of this clause to
the first statement of the next clause.
Otherwise control flows to the end of the "switch" statement.
+A "fallthrough" statement may appear as the last statement of all
+but the last clause of an expression switch.
</p>
<p>
@@ -4798,9 +4800,8 @@ the "for" statement's block but the <code>goto</code> is not.\n
<p>
A "fallthrough" statement transfers control to the first statement of the
-next case clause in a expression "switch" statement (§<a href="#Expression_switches">Expression switches</a>). It may
-be used only as the final non-empty statement in a case or default clause in an
-expression "switch" statement.\n+next case clause in a <a href="#Expression_switches">expression "switch" statement</a>.\n+It may be used only as the final non-empty statement in such a clause.\n </p>
<pre class="ebnf">\n
コアとなるコードの解説
このコミットは、Go言語の仕様書であるdoc/go_spec.html
ファイルを変更しています。
-
日付の更新:
Subtitle
が "Version of February 11, 2013" から "Version of March 1, 2013" に更新されています。これは、仕様書のバージョンがこの変更によって更新されたことを示します。
-
switch
ステートメントのセクション (#Expression_switches
) の変更:- 元の記述: "In a case or default clause, the last statement only may be a "fallthrough" statement..."
- 変更後: "In a case or default clause, the last non-empty statement may be a (possibly labeled) "fallthrough" statement to indicate that control should flow from the end of this clause to the first statement of the next clause. Otherwise control flows to the end of the "switch" statement. A "fallthrough" statement may appear as the last statement of all but the last clause of an expression switch."
- この変更のポイントは2つです。
fallthrough
が「(おそらくラベル付きの)」((possibly labeled)
) である可能性が明示されました。これは、fallthrough
が単なるキーワードではなく、ラベルを付けられるステートメントとして扱われることを明確にします。- 最も重要な変更は、太字で示した新しい文です。「
fallthrough
ステートメントは、式switch
の最後の節を除くすべての節の最後のステートメントとして現れることができる」と明記されました。これにより、fallthrough
がswitch
文の最後のcase
やdefault
節で使用された場合に、コンパイルエラーとなるべきという制約が仕様レベルで明確に定義されました。
-
fallthrough
ステートメントのセクション (#Fallthrough_statements
) の変更:- 元の記述: "It may be used only as the final non-empty statement in a case or default clause in an expression "switch" statement."
- 変更後: "It may be used only as the final non-empty statement in such a clause."
- この変更は、
fallthrough
ステートメントの一般的な説明から、switch
文の最後の節での使用に関する具体的な制約を削除し、その制約はswitch
ステートメントのセクションで一元的に記述されるように整理されました。これにより、仕様の記述が重複せず、より整合性が保たれます。
これらの変更により、Go言語のfallthrough
ステートメントの振る舞いに関する仕様がより明確になり、開発者が意図しないコードを書くことを防ぐことができます。
関連リンク
- GitHubコミットページ: https://github.com/golang/go/commit/67a6b4f0ef04e547e671230d84f96b00a2966113
- Go CL 7416048: https://golang.org/cl/7416048
- Go Issue #4923: https://github.com/golang/go/issues/4923
参考にした情報源リンク
- Go Language Specification - Switch statements: https://go.dev/ref/spec#Switch_statements
- Go Language Specification - Fallthrough statements: https://go.dev/ref/spec#Fallthrough_statements
- Go Language Specification - Labeled statements: https://go.dev/ref/spec#Labeled_statements
- Go CL 7370053 (Previous attempt, replaced by this CL): (直接的なリンクは見つかりませんでしたが、このコミットメッセージで言及されています。)
- Go issue 4923: spec: fallthrough may not appear in last clause of a switch: https://github.com/golang/go/issues/4923