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

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

このコミットは、Go言語の仕様書(doc/go_spec.html)におけるfallthroughステートメントの記述を修正するものです。具体的には、switch文の最後のcaseまたはdefault節ではfallthroughステートメントを使用できないという制約を明確にし、またfallthroughがラベルを持つ可能性があることを追記しています。これは、以前の関連する変更(CL 7370053)がfallthroughswitch文の構文の一部として扱おうとしたものの、ラベル付きステートメントとの兼ね合いで仕様の変更が複雑になりすぎたため、その代替として提案されました。この変更は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)の代替であり、その変更がfallthroughswitch文の構文の一部にしようとしたものの、fallthroughがラベルを持つ可能性があるため、仕様の変更が複雑になりすぎたために置き換えられました。このコミットはIssue #4923を修正します。

変更の背景

この変更の背景には、Go言語のswitchステートメントにおけるfallthroughキーワードの振る舞いと、その仕様記述に関する課題がありました。

Goのswitchステートメントは、他のC系の言語とは異なり、デフォルトでcase節の実行後に自動的に次のcase節に「フォールスルー」しません。各case節は暗黙的にbreakを含んでいるかのように振る舞います。しかし、明示的に次のcase節に制御を移したい場合にfallthroughキーワードを使用します。

問題は、fallthroughswitch文の最後のcase節やdefault節で使用された場合、次に実行すべきcase節が存在しないため、その振る舞いが未定義または無意味になる点でした。Go言語のIssue #4923は、この曖昧さを解消し、fallthroughが最後の節で使用された場合にコンパイルエラーとすべきであるという提案でした。

以前、CL 7370053という変更がこの問題に対処しようとしましたが、そのアプローチはfallthroughswitch文の構文規則に直接組み込むものでした。しかし、Go言語ではfallthroughステートメントも他のステートメントと同様にラベルを持つことが可能です(例: MyLabel: fallthrough)。この「ラベル付きfallthrough」という特性が、fallthroughswitch構文の一部として厳密に定義しようとすると、仕様書全体の「手術」(spec surgery)が必要になるほど複雑な変更を伴うことが判明しました。

そのため、このコミット(CL 7416048)は、以前のCL 7370053の代替として、よりシンプルかつ直接的な方法でこの問題を解決することを目指しました。すなわち、fallthroughswitchの最後の節に現れてはならないという制約を、仕様書のテキスト記述として明確に追加することで、複雑な構文変更を避けるアプローチが取られました。

前提知識の解説

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」セクションの記述を更新しています。

主な変更点:

  1. 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節を持たない場所で使用されることによる曖昧さが解消されます。

  2. 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ファイルを変更しています。

  1. 日付の更新:

    • Subtitleが "Version of February 11, 2013" から "Version of March 1, 2013" に更新されています。これは、仕様書のバージョンがこの変更によって更新されたことを示します。
  2. 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の最後の節を除くすべての節の最後のステートメントとして現れることができる」と明記されました。これにより、fallthroughswitch文の最後のcasedefault節で使用された場合に、コンパイルエラーとなるべきという制約が仕様レベルで明確に定義されました。
  3. 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ステートメントの振る舞いに関する仕様がより明確になり、開発者が意図しないコードを書くことを防ぐことができます。

関連リンク

参考にした情報源リンク