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

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

このコミットは、Go言語の仕様書(doc/go_spec.html)に対する変更であり、Go言語のswitchステートメント、特に型スイッチ(type switch)の構文とセマンティクスを簡素化することを目的としています。具体的には、switch文のcase節内で型アサーションやマップのルックアップ、チャネルの受信操作の結果として得られる値, okok部分を暗黙的に利用する特殊な形式のswitch(通称「,ok switch」)を廃止し、より直接的で明確な型スイッチの形式に統一しています。

コミット

commit 70c1a106e609f7d38f8fe7fb7c999f2fba
Author: Rob Pike <r@golang.org>
Date:   Wed Mar 18 19:23:59 2009 -0700

    drop the ,ok switch; keep the straight type switch.
    
    R=rsc,gri
    DELTA=97  (26 added, 42 deleted, 29 changed)
    OCL=26436
    CL=26527

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

https://github.com/golang/go/commit/70c1a106e609f7d38f8fe7fb7c93070e999f2fba

元コミット内容

このコミットの元の内容は、Go言語の仕様書から、switchステートメントの特定の形式、特にbool_exprを評価し、そのcase節で型アサーション(x1 := y1.(T1))、マップのルックアップ(x2 := y2[z2])、チャネルの受信(x3 := <-y3)といった操作の結果として得られるokブール値を利用する構文を削除することです。これにより、switch文の複雑さを軽減し、型スイッチのセマンティクスをより一貫性のあるものにしています。

変更の背景

Go言語の初期段階では、switchステートメントには現在よりも柔軟で、時には複雑な構文が存在していました。このコミットが行われた2009年3月は、Go言語がまだ活発に設計・開発されていた時期であり、言語のセマンティクスや構文が頻繁に洗練されていました。

この変更の背景には、以下の点が考えられます。

  1. 構文の簡素化と一貫性: 初期に存在した「,ok switch」の形式は、switch文がブール値を評価し、そのcase節で型アサーションなどの結果のok値と照合するという、やや特殊なセマンティクスを持っていました。これは、通常の式スイッチや型スイッチとは異なる振る舞いをし、言語の学習曲線や理解を複雑にする可能性がありました。このコミットは、switch文の構文をよりシンプルで予測可能なものに統一し、特に型スイッチをその名の通り「型」に特化した比較を行うものとして明確に位置づけることを目指しています。
  2. 冗長性の排除: if/else if文でokイディオム(例: if val, ok := interface{}.(Type); ok { ... })を使用することで、同様のロジックを表現できるため、特殊な「,ok switch」構文は冗長であると判断された可能性があります。Go言語の設計哲学は、多くの場合、複数の方法で同じことを行うことを避け、最も明確で慣用的な方法を推奨します。
  3. 言語設計の成熟: 言語が成熟するにつれて、初期の実験的な機能や構文が再評価され、より堅牢で使いやすい設計に収束していく過程の一部です。この変更は、Go言語の設計者が、よりクリーンで直感的な言語仕様を目指していたことを示しています。

前提知識の解説

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

  1. switch ステートメント:

    • Go言語のswitchステートメントは、他の多くの言語と同様に、複数の条件分岐を簡潔に記述するための制御構造です。
    • 式スイッチ (Expression Switch): switchキーワードの後に式を置き、その式の値とcase節の値を比較します。式が省略された場合は、trueが評価されます。
    • 型スイッチ (Type Switch): インターフェース型の変数の動的な型に基づいて分岐を行う特殊なswitchです。switchキーワードの後に変数 := インターフェース変数.(type)という形式で記述します。
  2. 型アサーション (Type Assertion):

    • インターフェース型の変数が、特定の具象型を保持しているかどうかを確認し、その具象型の値を取り出すための操作です。
    • 構文はvalue, ok := interfaceValue.(Type)です。ここでvalueは具象型の値、okはアサーションが成功したかどうかを示すブール値です。ok変数を省略してvalue := interfaceValue.(Type)と書くこともできますが、この場合、アサーションが失敗するとパニックが発生します。
  3. マップのルックアップ (Map Lookup):

    • マップからキーに対応する値を取得する操作です。
    • 構文はvalue, ok := map[key]です。ここでvalueはキーに対応する値、okはキーが存在したかどうかを示すブール値です。
  4. チャネルの受信 (Channel Receive):

    • チャネルから値を受信する操作です。
    • 構文はvalue, ok := <-channelです。ここでvalueは受信した値、okはチャネルが閉じられていないか、または値が正常に受信されたかどうかを示すブール値です。

これらの操作で返されるokブール値は、Go言語における「カンマokイディオム」として知られており、操作の成功/失敗を明示的に扱うためのGoの慣用的なパターンです。

技術的詳細

このコミットの技術的な詳細は、Go言語の仕様書から「,ok switch」の構文とセマンティクスを完全に削除し、型スイッチの定義をより厳密にすることにあります。

削除された「,ok switch」の形式は、以下のようなものでした(コミット前の仕様書から推測される構文):

switch bool_expr {
case x1 := y1.(T1): // 型アサーション
    f1()
case x2 := y2[z2]: // マップルックアップ
    f2()
case x3 := <-y3: // チャネル受信
    f3()
default:
    f4()
}

この構文では、switchの式bool_exprtrueであるかfalseであるかに応じて、case節内の操作(型アサーション、マップルックアップ、チャネル受信)のokブール値がbool_exprと一致するかどうかで分岐していました。例えば、bool_exprtrueの場合、case x1 := y1.(T1):y1.(T1)が成功しoktrueを返す場合に実行されました。

このコミットにより、上記の特殊なswitch形式はGo言語の仕様から削除されました。その結果、switchステートメントは以下の2つの主要な形式に明確に分けられました。

  1. 式スイッチ (Expression Switch): switchの式が評価され、その値がcase節の式と比較されます。case節は純粋な式のみを含みます。
  2. 型スイッチ (Type Switch): switchの式がインターフェース変数.(type)の形式で、case節は具体的な型名を含みます。この形式では、インターフェース変数がそのcase節で指定された型を保持している場合に分岐が実行されます。

コミット後の型スイッチの定義は、よりシンプルで直接的になりました。型スイッチは、インターフェース変数の動的な型を直接比較するものであり、okイディオムを暗黙的に利用する複雑なロジックは含まれません。型スイッチのcase節では、型アサーションの結果として新しい変数を宣言できますが、これはそのcase節のスコープ内でのみ有効であり、okブール値の評価とは直接関係ありません。

また、コミットによって、型スイッチに関する以下の制約が明確化されました。

  • 型スイッチでは、ガード(変数 := インターフェース変数.(type)の部分)が必須です。
  • case節には、1つの型のみを指定できます。
  • fallthroughステートメントは許可されません。

これらの変更は、Go言語のswitchステートメントのセマンティクスをより明確にし、開発者がコードの挙動を予測しやすくすることを目的としています。

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

このコミットは、Go言語のランタイムやコンパイラのコード自体を変更するものではなく、Go言語の仕様書であるdoc/go_spec.htmlファイルを変更しています。

具体的には、以下のセダクションが変更されています。

  • doc/go_spec.html内のSwitch statementsセクション。
  • 特に、Expression switchesType switchesに関する説明、文法定義(pre class="grammar"ブロック)、および例が修正されています。

変更のハイライトは以下の通りです。

  • switch bool_exprという形式の特殊なswitch文の記述と、それに対応するif/else ifへの書き換え例が完全に削除されました。
  • TypeSwitchStatの文法定義が簡素化され、TypeSwitchGuardという新しい非終端記号が導入されました。
  • ExprSwitchStatの文法定義も更新され、ExprCaseClauseExprSwitchCaseが導入されました。
  • 型スイッチの例が簡素化され、switch val := f(); true { ... }のような形式が削除され、より直接的な型スイッチの例に置き換えられました。
  • 型スイッチのセマンティクスに関する新しい制約(ガードの必須性、caseごとの型の数、fallthroughの禁止)が明記されました。

コアとなるコードの解説

このコミットにおける「コアとなるコード」は、Go言語の仕様書であるdoc/go_spec.htmlです。このファイルは、Go言語の構文、セマンティクス、および標準ライブラリの動作を定義する公式ドキュメントです。

変更の解説は以下の通りです。

  1. doc/go_spec.htmlの変更:
    • 削除されたセクション:
      • switch bool_exprに関する詳細な説明と、型アサーション、マップルックアップ、チャネル受信のok値を利用するcase節の例が削除されました。これは、この特殊なswitch形式が言語仕様から完全に排除されたことを意味します。
      • この特殊なswitchif/else if文にどのように書き換えられるかを示す冗長な例も削除されました。
    • Expression switchesの更新:
      • ExprSwitchStatの文法定義が更新され、ExprCaseClauseExprSwitchCaseが導入されました。これにより、式スイッチのcase節の構造がより明確になりました。
      • A missing expression is equivalent to the expression <code>true</code>.という文が、より適切な位置に移動されました。
    • Type switchesの更新:
      • TypeSwitchStatの文法定義が更新され、TypeSwitchGuardが導入されました。これは、型スイッチのガード部分(identifier := Expression . ( type ))を明示的に定義します。
      • 型スイッチの動作に関する説明が簡素化され、以前の「式スイッチとして書き換え可能」という記述が削除されました。これは、型スイッチが独自のセマンティクスを持つ独立した構文であることを強調しています。
      • 型スイッチの例が、より直接的な形式に修正されました。
      • 型スイッチのcase節で宣言される変数のスコープに関する説明が維持されています。
      • 新しい制約の追加: 型スイッチには、ガードが必須であること、case節ごとに1つの型のみが許可されること、fallthroughが許可されないことという、重要な制約が追加されました。これらは、型スイッチの振る舞いをより厳密に定義し、潜在的な混乱を避けるためのものです。

これらの変更は、Go言語のswitchステートメントの設計を洗練し、特に型スイッチをより明確で使いやすいものにするための重要なステップでした。言語仕様の変更は、Goコンパイラやツールが将来的にこの新しい仕様に準拠して動作することを意味します。

関連リンク

参考にした情報源リンク

  • Go言語のコミット履歴 (GitHub): https://github.com/golang/go/commits/master
  • Go言語の初期の設計に関する議論やメーリングリストのアーカイブ (もし公開されていれば、当時の設計判断の背景を深く理解するのに役立つ可能性がありますが、具体的なリンクは特定できませんでした。)
  • Go言語のswitchステートメントに関する一般的な解説記事やチュートリアル。

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

このコミットは、Go言語の仕様書(doc/go_spec.html)に対する変更であり、Go言語のswitchステートメント、特に型スイッチ(type switch)の構文とセマンティクスを簡素化することを目的としています。具体的には、switch文のcase節内で型アサーションやマップのルックアップ、チャネルの受信操作の結果として得られる値, okok部分を暗黙的に利用する特殊な形式のswitch(通称「,ok switch」)を廃止し、より直接的で明確な型スイッチの形式に統一しています。

コミット

commit 70c1a106e609f7d38f8fe7fb7c999f2fba
Author: Rob Pike <r@golang.org>
Date:   Wed Mar 18 19:23:59 2009 -0700

    drop the ,ok switch; keep the straight type switch.
    
    R=rsc,gri
    DELTA=97  (26 added, 42 deleted, 29 changed)
    OCL=26436
    CL=26527

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

https://github.com/golang/go/commit/70c1a106e609f7d38f8fe7fb7c93070e999f2fba

元コミット内容

このコミットの元の内容は、Go言語の仕様書から、switchステートメントの特定の形式、特にbool_exprを評価し、そのcase節で型アサーション(x1 := y1.(T1))、マップのルックアップ(x2 := y2[z2])、チャネルの受信(x3 := <-y3)といった操作の結果として得られるokブール値を利用する構文を削除することです。これにより、switch文の複雑さを軽減し、型スイッチのセマンティクスをより一貫性のあるものにしています。

変更の背景

Go言語の初期段階では、switchステートメントには現在よりも柔軟で、時には複雑な構文が存在していました。このコミットが行われた2009年3月は、Go言語がまだ活発に設計・開発されていた時期であり、言語のセマンティクスや構文が頻繁に洗練されていました。

この変更の背景には、以下の点が考えられます。

  1. 構文の簡素化と一貫性: 初期に存在した「,ok switch」の形式は、switch文がブール値を評価し、そのcase節で型アサーションなどの結果のok値と照合するという、やや特殊なセマンティクスを持っていました。これは、通常の式スイッチや型スイッチとは異なる振る舞いをし、言語の学習曲線や理解を複雑にする可能性がありました。このコミットは、switch文の構文をよりシンプルで予測可能なものに統一し、特に型スイッチをその名の通り「型」に特化した比較を行うものとして明確に位置づけることを目指しています。
  2. 冗長性の排除: if/else if文でokイディオム(例: if val, ok := interface{}.(Type); ok { ... })を使用することで、同様のロジックを表現できるため、特殊な「,ok switch」構文は冗長であると判断された可能性があります。Go言語の設計哲学は、多くの場合、複数の方法で同じことを行うことを避け、最も明確で慣用的な方法を推奨します。
  3. 言語設計の成熟: 言語が成熟するにつれて、初期の実験的な機能や構文が再評価され、より堅牢で使いやすい設計に収束していく過程の一部です。この変更は、Go言語の設計者が、よりクリーンで直感的な言語仕様を目指していたことを示しています。

前提知識の解説

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

  1. switch ステートメント:

    • Go言語のswitchステートメントは、他の多くの言語と同様に、複数の条件分岐を簡潔に記述するための制御構造です。
    • 式スイッチ (Expression Switch): switchキーワードの後に式を置き、その式の値とcase節の値を比較します。式が省略された場合は、trueが評価されます。
    • 型スイッチ (Type Switch): インターフェース型の変数の動的な型に基づいて分岐を行う特殊なswitchです。switchキーワードの後に変数 := インターフェース変数.(type)という形式で記述します。
  2. 型アサーション (Type Assertion):

    • インターフェース型の変数が、特定の具象型を保持しているかどうかを確認し、その具象型の値を取り出すための操作です。
    • 構文はvalue, ok := interfaceValue.(Type)です。ここでvalueは具象型の値、okはアサーションが成功したかどうかを示すブール値です。ok変数を省略してvalue := interfaceValue.(Type)と書くこともできますが、この場合、アサーションが失敗するとパニックが発生します。
  3. マップのルックアップ (Map Lookup):

    • マップからキーに対応する値を取得する操作です。
    • 構文はvalue, ok := map[key]です。ここでvalueはキーに対応する値、okはキーが存在したかどうかを示すブール値です。
  4. チャネルの受信 (Channel Receive):

    • チャネルから値を受信する操作です。
    • 構文はvalue, ok := <-channelです。ここでvalueは受信した値、okはチャネルが閉じられていないか、または値が正常に受信されたかどうかを示すブール値です。

これらの操作で返されるokブール値は、Go言語における「カンマokイディオム」として知られており、操作の成功/失敗を明示的に扱うためのGoの慣用的なパターンです。

技術的詳細

このコミットの技術的な詳細は、Go言語の仕様書から「,ok switch」の構文とセマンティクスを完全に削除し、型スイッチの定義をより厳密にすることにあります。

削除された「,ok switch」の形式は、以下のようなものでした(コミット前の仕様書から推測される構文):

switch bool_expr {
case x1 := y1.(T1): // 型アサーション
    f1()
case x2 := y2[z2]: // マップルックアップ
    f2()
case x3 := <-y3: // チャネル受信
    f3()
default:
    f4()
}

この構文では、switchの式bool_exprtrueであるかfalseであるかに応じて、case節内の操作(型アサーション、マップルックアップ、チャネル受信)のokブール値がbool_exprと一致するかどうかで分岐していました。例えば、bool_exprtrueの場合、case x1 := y1.(T1):y1.(T1)が成功しoktrueを返す場合に実行されました。

このコミットにより、上記の特殊なswitch形式はGo言語の仕様から削除されました。その結果、switchステートメントは以下の2つの主要な形式に明確に分けられました。

  1. 式スイッチ (Expression Switch): switchの式が評価され、その値がcase節の式と比較されます。case節は純粋な式のみを含みます。
  2. 型スイッチ (Type Switch): switchの式がインターフェース変数.(type)の形式で、case節は具体的な型名を含みます。この形式では、インターフェース変数がそのcase節で指定された型を保持している場合に分岐が実行されます。

コミット後の型スイッチの定義は、よりシンプルで直接的になりました。型スイッチは、インターフェース変数の動的な型を直接比較するものであり、okイディオムを暗黙的に利用する複雑なロジックは含まれません。型スイッチのcase節では、型アサーションの結果として新しい変数を宣言できますが、これはそのcase節のスコープ内でのみ有効であり、okブール値の評価とは直接関係ありません。

また、コミットによって、型スイッチに関する以下の制約が明確化されました。

  • 型スイッチでは、ガード(変数 := インターフェース変数.(type)の部分)が必須です。
  • case節には、1つの型のみを指定できます。
  • fallthroughステートメントは許可されません。

これらの変更は、Go言語のswitchステートメントのセマンティクスをより明確にし、開発者がコードの挙動を予測しやすくすることを目的としています。

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

このコミットは、Go言語のランタイムやコンパイラのコード自体を変更するものではなく、Go言語の仕様書であるdoc/go_spec.htmlファイルを変更しています。

具体的には、以下のセダクションが変更されています。

  • doc/go_spec.html内のSwitch statementsセクション。
  • 特に、Expression switchesType switchesに関する説明、文法定義(pre class="grammar"ブロック)、および例が修正されています。

変更のハイライトは以下の通りです。

  • switch bool_exprという形式の特殊なswitch文の記述と、それに対応するif/else ifへの書き換え例が完全に削除されました。
  • TypeSwitchStatの文法定義が簡素化され、TypeSwitchGuardという新しい非終端記号が導入されました。
  • ExprSwitchStatの文法定義も更新され、ExprCaseClauseExprSwitchCaseが導入されました。
  • 型スイッチの例が簡素化され、switch val := f(); true { ... }のような形式が削除され、より直接的な型スイッチの例に置き換えられました。
  • 型スイッチのセマンティクスに関する新しい制約(ガードの必須性、caseごとの型の数、fallthroughの禁止)が明記されました。

コアとなるコードの解説

このコミットにおける「コアとなるコード」は、Go言語の仕様書であるdoc/go_spec.htmlです。このファイルは、Go言語の構文、セマンティクス、および標準ライブラリの動作を定義する公式ドキュメントです。

変更の解説は以下の通りです。

  1. doc/go_spec.htmlの変更:
    • 削除されたセクション:
      • switch bool_exprに関する詳細な説明と、型アサーション、マップルックアップ、チャネル受信のok値を利用するcase節の例が削除されました。これは、この特殊なswitch形式が言語仕様から完全に排除されたことを意味します。
      • この特殊なswitchif/else if文にどのように書き換えられるかを示す冗長な例も削除されました。
    • Expression switchesの更新:
      • ExprSwitchStatの文法定義が更新され、ExprCaseClauseExprSwitchCaseが導入されました。これにより、式スイッチのcase節の構造がより明確になりました。
      • A missing expression is equivalent to the expression <code>true</code>.という文が、より適切な位置に移動されました。
    • Type switchesの更新:
      • TypeSwitchStatの文法定義が更新され、TypeSwitchGuardが導入されました。これは、型スイッチのガード部分(identifier := Expression . ( type ))を明示的に定義します。
      • 型スイッチの動作に関する説明が簡素化され、以前の「式スイッチとして書き換え可能」という記述が削除されました。これは、型スイッチが独自のセマンティクスを持つ独立した構文であることを強調しています。
      • 型スイッチの例が、より直接的な形式に修正されました。
      • 型スイッチのcase節で宣言される変数のスコープに関する説明が維持されています。
      • 新しい制約の追加: 型スイッチには、ガードが必須であること、case節ごとに1つの型のみが許可されること、fallthroughが許可されないことという、重要な制約が追加されました。これらは、型スイッチの振る舞いをより厳密に定義し、潜在的な混乱を避けるためのものです。

これらの変更は、Go言語のswitchステートメントの設計を洗練し、特に型スイッチをより明確で使いやすいものにするための重要なステップでした。言語仕様の変更は、Goコンパイラやツールが将来的にこの新しい仕様に準拠して動作することを意味します。

関連リンク

参考にした情報源リンク

  • Go言語のコミット履歴 (GitHub): https://github.com/golang/go/commits/master
  • Go言語の初期の設計に関する議論やメーリングリストのアーカイブ (もし公開されていれば、当時の設計判断の背景を深く理解するのに役立つ可能性がありますが、具体的なリンクは特定できませんでした。)
  • Go言語のswitchステートメントに関する一般的な解説記事やチュートリアル。