NO IMAGE

【Go】ブロックとスコープについてまとめてみる

NO IMAGE

Go言語には、公式が提供している言語仕様ドキュメントが存在します。これまでにもこの仕様書の精読がススメられていたり、なんちゃって日本語訳がまとめられていたりするのですが、今回あらためて、自分でも少しずつまとめていけたらと思ってこの記事を書きました。

今回はGoで関連の深い、ブロックとスコープをセットにして紹介します。

ブロック

Goにおけるブロック(block)は、波括弧で囲われた内部の宣言と文の列を指します。基本的に、ブロックはソースコード内で明示的にあらわれますが、言語仕様のドキュメントによると、以下のような暗黙的なブロックもあります。

  • すべてのGoコードを包含するユニバースブロック(universe block)
  • それぞれのパッケージ内のすべてのGoコードを包含するパッケージブロック(package block)
  • それぞれの.go拡張子ファイル内のすべてのGoコードを包含するファイルブロック(file block)
  • それぞれのif, for, switch文はそれ自身が暗黙的なブロックと見なされます
  • switch、およびselect文の各句は暗黙的なブロックと見なされます

これらのブロックは、以下に見るGo識別子のスコープに影響を与えています。

スコープ

何かしらの定数、変数や関数として宣言された識別子(identifier)は、ブロックの仕様を用いて字句的にスコープ(lexically scoped)されます。

  1. 事前宣言された識別子のスコープは、ユニバースブロックになります。ちなみに、事前宣言された識別子のリストは以下の通りです。
型:
	bool byte complex64 complex128 error float32 float64
	int int8 int16 int32 int64 rune string
	uint uint8 uint16 uint32 uint64 uintptr

定数:
	true false iota

ゼロ値:
	nil

関数:
	append cap close complex copy delete imag len
	make new panic print println real recover
  1. トップレベルで宣言された定数,型,変数,関数 (メソッドは除く)を示す識別子のスコープは, パッケージブロックになります。
  2. インポートされたパッケージのパッケージ名のスコープは, インポート宣言をしたファイルのファイルブロックになります。
  3. メソッドレシーバー,関数パラメーター,復帰変数を示す識別子のスコープは, 関数それ自体(function body)となります。
  4. 関数の型パラメータを示す識別子、あるいはメソッドレシーバで宣言された識別子のスコープは、関数それ自体と関数の全パラメータリスト(all parameter lists of the function)となります。
  5. ある型の型パラメータを示す識別子のスコープは、その型の名前の後から、TypeSpecの終点までとなります。
  6. 関数の内部で宣言された定数、あるいは変数識別子のスコープは、ConstSpec/VarSpecの終点から始まり、最も内側を囲むブロックの終点で終わります。
  7. 関数の内部で宣言された型識別子のスコープは、TypeSpecの識別子から始まり、最も内側を囲むブロックの終点で終わります。

参考