[インデックス 1849] ファイルの概要
このコミットは、Go言語の仕様書(doc/go_spec.html
)に対する変更であり、Go言語のswitch
ステートメント、特に型スイッチ(type switch)の構文とセマンティクスを簡素化することを目的としています。具体的には、switch
文のcase
節内で型アサーションやマップのルックアップ、チャネルの受信操作の結果として得られる値, ok
のok
部分を暗黙的に利用する特殊な形式の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言語がまだ活発に設計・開発されていた時期であり、言語のセマンティクスや構文が頻繁に洗練されていました。
この変更の背景には、以下の点が考えられます。
- 構文の簡素化と一貫性: 初期に存在した「
,ok
switch」の形式は、switch
文がブール値を評価し、そのcase
節で型アサーションなどの結果のok
値と照合するという、やや特殊なセマンティクスを持っていました。これは、通常の式スイッチや型スイッチとは異なる振る舞いをし、言語の学習曲線や理解を複雑にする可能性がありました。このコミットは、switch
文の構文をよりシンプルで予測可能なものに統一し、特に型スイッチをその名の通り「型」に特化した比較を行うものとして明確に位置づけることを目指しています。 - 冗長性の排除:
if/else if
文でok
イディオム(例:if val, ok := interface{}.(Type); ok { ... }
)を使用することで、同様のロジックを表現できるため、特殊な「,ok
switch」構文は冗長であると判断された可能性があります。Go言語の設計哲学は、多くの場合、複数の方法で同じことを行うことを避け、最も明確で慣用的な方法を推奨します。 - 言語設計の成熟: 言語が成熟するにつれて、初期の実験的な機能や構文が再評価され、より堅牢で使いやすい設計に収束していく過程の一部です。この変更は、Go言語の設計者が、よりクリーンで直感的な言語仕様を目指していたことを示しています。
前提知識の解説
このコミットの変更内容を理解するためには、Go言語における以下の概念を理解しておく必要があります。
-
switch
ステートメント:- Go言語の
switch
ステートメントは、他の多くの言語と同様に、複数の条件分岐を簡潔に記述するための制御構造です。 - 式スイッチ (Expression Switch):
switch
キーワードの後に式を置き、その式の値とcase
節の値を比較します。式が省略された場合は、true
が評価されます。 - 型スイッチ (Type Switch): インターフェース型の変数の動的な型に基づいて分岐を行う特殊な
switch
です。switch
キーワードの後に変数 := インターフェース変数.(type)
という形式で記述します。
- Go言語の
-
型アサーション (Type Assertion):
- インターフェース型の変数が、特定の具象型を保持しているかどうかを確認し、その具象型の値を取り出すための操作です。
- 構文は
value, ok := interfaceValue.(Type)
です。ここでvalue
は具象型の値、ok
はアサーションが成功したかどうかを示すブール値です。ok
変数を省略してvalue := interfaceValue.(Type)
と書くこともできますが、この場合、アサーションが失敗するとパニックが発生します。
-
マップのルックアップ (Map Lookup):
- マップからキーに対応する値を取得する操作です。
- 構文は
value, ok := map[key]
です。ここでvalue
はキーに対応する値、ok
はキーが存在したかどうかを示すブール値です。
-
チャネルの受信 (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_expr
がtrue
であるかfalse
であるかに応じて、case
節内の操作(型アサーション、マップルックアップ、チャネル受信)のok
ブール値がbool_expr
と一致するかどうかで分岐していました。例えば、bool_expr
がtrue
の場合、case x1 := y1.(T1):
はy1.(T1)
が成功しok
がtrue
を返す場合に実行されました。
このコミットにより、上記の特殊なswitch
形式はGo言語の仕様から削除されました。その結果、switch
ステートメントは以下の2つの主要な形式に明確に分けられました。
- 式スイッチ (Expression Switch):
switch
の式が評価され、その値がcase
節の式と比較されます。case
節は純粋な式のみを含みます。 - 型スイッチ (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 switches
とType switches
に関する説明、文法定義(pre class="grammar"
ブロック)、および例が修正されています。
変更のハイライトは以下の通りです。
switch bool_expr
という形式の特殊なswitch
文の記述と、それに対応するif/else if
への書き換え例が完全に削除されました。TypeSwitchStat
の文法定義が簡素化され、TypeSwitchGuard
という新しい非終端記号が導入されました。ExprSwitchStat
の文法定義も更新され、ExprCaseClause
とExprSwitchCase
が導入されました。- 型スイッチの例が簡素化され、
switch val := f(); true { ... }
のような形式が削除され、より直接的な型スイッチの例に置き換えられました。 - 型スイッチのセマンティクスに関する新しい制約(ガードの必須性、
case
ごとの型の数、fallthrough
の禁止)が明記されました。
コアとなるコードの解説
このコミットにおける「コアとなるコード」は、Go言語の仕様書であるdoc/go_spec.html
です。このファイルは、Go言語の構文、セマンティクス、および標準ライブラリの動作を定義する公式ドキュメントです。
変更の解説は以下の通りです。
doc/go_spec.html
の変更:- 削除されたセクション:
switch bool_expr
に関する詳細な説明と、型アサーション、マップルックアップ、チャネル受信のok
値を利用するcase
節の例が削除されました。これは、この特殊なswitch
形式が言語仕様から完全に排除されたことを意味します。- この特殊な
switch
がif/else if
文にどのように書き換えられるかを示す冗長な例も削除されました。
Expression switches
の更新:ExprSwitchStat
の文法定義が更新され、ExprCaseClause
とExprSwitchCase
が導入されました。これにより、式スイッチの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言語の公式ドキュメント: https://go.dev/doc/
- Go言語仕様: https://go.dev/ref/spec (このコミットが変更したドキュメントの最新版)
参考にした情報源リンク
- Go言語のコミット履歴 (GitHub): https://github.com/golang/go/commits/master
- Go言語の初期の設計に関する議論やメーリングリストのアーカイブ (もし公開されていれば、当時の設計判断の背景を深く理解するのに役立つ可能性がありますが、具体的なリンクは特定できませんでした。)
- Go言語の
switch
ステートメントに関する一般的な解説記事やチュートリアル。
[インデックス 1849] ファイルの概要
このコミットは、Go言語の仕様書(doc/go_spec.html
)に対する変更であり、Go言語のswitch
ステートメント、特に型スイッチ(type switch)の構文とセマンティクスを簡素化することを目的としています。具体的には、switch
文のcase
節内で型アサーションやマップのルックアップ、チャネルの受信操作の結果として得られる値, ok
のok
部分を暗黙的に利用する特殊な形式の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言語がまだ活発に設計・開発されていた時期であり、言語のセマンティクスや構文が頻繁に洗練されていました。
この変更の背景には、以下の点が考えられます。
- 構文の簡素化と一貫性: 初期に存在した「
,ok
switch」の形式は、switch
文がブール値を評価し、そのcase
節で型アサーションなどの結果のok
値と照合するという、やや特殊なセマンティクスを持っていました。これは、通常の式スイッチや型スイッチとは異なる振る舞いをし、言語の学習曲線や理解を複雑にする可能性がありました。このコミットは、switch
文の構文をよりシンプルで予測可能なものに統一し、特に型スイッチをその名の通り「型」に特化した比較を行うものとして明確に位置づけることを目指しています。 - 冗長性の排除:
if/else if
文でok
イディオム(例:if val, ok := interface{}.(Type); ok { ... }
)を使用することで、同様のロジックを表現できるため、特殊な「,ok
switch」構文は冗長であると判断された可能性があります。Go言語の設計哲学は、多くの場合、複数の方法で同じことを行うことを避け、最も明確で慣用的な方法を推奨します。 - 言語設計の成熟: 言語が成熟するにつれて、初期の実験的な機能や構文が再評価され、より堅牢で使いやすい設計に収束していく過程の一部です。この変更は、Go言語の設計者が、よりクリーンで直感的な言語仕様を目指していたことを示しています。
前提知識の解説
このコミットの変更内容を理解するためには、Go言語における以下の概念を理解しておく必要があります。
-
switch
ステートメント:- Go言語の
switch
ステートメントは、他の多くの言語と同様に、複数の条件分岐を簡潔に記述するための制御構造です。 - 式スイッチ (Expression Switch):
switch
キーワードの後に式を置き、その式の値とcase
節の値を比較します。式が省略された場合は、true
が評価されます。 - 型スイッチ (Type Switch): インターフェース型の変数の動的な型に基づいて分岐を行う特殊な
switch
です。switch
キーワードの後に変数 := インターフェース変数.(type)
という形式で記述します。
- Go言語の
-
型アサーション (Type Assertion):
- インターフェース型の変数が、特定の具象型を保持しているかどうかを確認し、その具象型の値を取り出すための操作です。
- 構文は
value, ok := interfaceValue.(Type)
です。ここでvalue
は具象型の値、ok
はアサーションが成功したかどうかを示すブール値です。ok
変数を省略してvalue := interfaceValue.(Type)
と書くこともできますが、この場合、アサーションが失敗するとパニックが発生します。
-
マップのルックアップ (Map Lookup):
- マップからキーに対応する値を取得する操作です。
- 構文は
value, ok := map[key]
です。ここでvalue
はキーに対応する値、ok
はキーが存在したかどうかを示すブール値です。
-
チャネルの受信 (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_expr
がtrue
であるかfalse
であるかに応じて、case
節内の操作(型アサーション、マップルックアップ、チャネル受信)のok
ブール値がbool_expr
と一致するかどうかで分岐していました。例えば、bool_expr
がtrue
の場合、case x1 := y1.(T1):
はy1.(T1)
が成功しok
がtrue
を返す場合に実行されました。
このコミットにより、上記の特殊なswitch
形式はGo言語の仕様から削除されました。その結果、switch
ステートメントは以下の2つの主要な形式に明確に分けられました。
- 式スイッチ (Expression Switch):
switch
の式が評価され、その値がcase
節の式と比較されます。case
節は純粋な式のみを含みます。 - 型スイッチ (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 switches
とType switches
に関する説明、文法定義(pre class="grammar"
ブロック)、および例が修正されています。
変更のハイライトは以下の通りです。
switch bool_expr
という形式の特殊なswitch
文の記述と、それに対応するif/else if
への書き換え例が完全に削除されました。TypeSwitchStat
の文法定義が簡素化され、TypeSwitchGuard
という新しい非終端記号が導入されました。ExprSwitchStat
の文法定義も更新され、ExprCaseClause
とExprSwitchCase
が導入されました。- 型スイッチの例が簡素化され、
switch val := f(); true { ... }
のような形式が削除され、より直接的な型スイッチの例に置き換えられました。 - 型スイッチのセマンティクスに関する新しい制約(ガードの必須性、
case
ごとの型の数、fallthrough
の禁止)が明記されました。
コアとなるコードの解説
このコミットにおける「コアとなるコード」は、Go言語の仕様書であるdoc/go_spec.html
です。このファイルは、Go言語の構文、セマンティクス、および標準ライブラリの動作を定義する公式ドキュメントです。
変更の解説は以下の通りです。
doc/go_spec.html
の変更:- 削除されたセクション:
switch bool_expr
に関する詳細な説明と、型アサーション、マップルックアップ、チャネル受信のok
値を利用するcase
節の例が削除されました。これは、この特殊なswitch
形式が言語仕様から完全に排除されたことを意味します。- この特殊な
switch
がif/else if
文にどのように書き換えられるかを示す冗長な例も削除されました。
Expression switches
の更新:ExprSwitchStat
の文法定義が更新され、ExprCaseClause
とExprSwitchCase
が導入されました。これにより、式スイッチの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言語の公式ドキュメント: https://go.dev/doc/
- Go言語仕様: https://go.dev/ref/spec (このコミットが変更したドキュメントの最新版)
参考にした情報源リンク
- Go言語のコミット履歴 (GitHub): https://github.com/golang/go/commits/master
- Go言語の初期の設計に関する議論やメーリングリストのアーカイブ (もし公開されていれば、当時の設計判断の背景を深く理解するのに役立つ可能性がありますが、具体的なリンクは特定できませんでした。)
- Go言語の
switch
ステートメントに関する一般的な解説記事やチュートリアル。