Go/識別子のスコープ
表示
< Go
Goにおける識別子のスコープは、特定の識別子(変数名、関数名、型名など)がコードのどの部分から参照可能かを決定するものです。Goには主に以下の3つのスコープがあります。
- ブロック・スコープ (Block Scope)
- パッケージ・スコープ (Package Scope)
- ユニバース・スコープ (Universe Scope)
1. ブロック・スコープ (Block Scope)
[編集]ブロック・スコープは、最も限定的なスコープです。{}で囲まれたブロック内で宣言された識別子(変数、定数など)は、そのブロック内でのみ有効です。
- 特徴
if文、for文、switch文、関数本体などのブロック内で宣言された変数や定数。- そのブロックが終了すると、識別子はスコープ外となり、アクセスできなくなります。
- ネストされたブロックでは、外側のブロックの識別子にアクセスできますが、内側のブロックで同じ名前の識別子を宣言すると、内側の識別子が優先されます(シャドーイング)。
- 例
package main import "fmt" func main() { x := 10 // main関数のブロックスコープ if x > 5 { y := 20 // if文のブロックスコープ fmt.Println("x:", x) // アクセス可能 fmt.Println("y:", y) // アクセス可能 } // fmt.Println("y:", y) // エラー: yはifブロック外ではアクセスできない } func anotherFunc() { // fmt.Println("x:", x) // エラー: xはmain関数のブロックスコープに限定される }
2. パッケージ・スコープ (Package Scope)
[編集]パッケージ・スコープは、特定のパッケージ内で有効なスコープです。Goでは、識別子名の先頭の文字が大文字か小文字かによって、その可視性が決まります。
- 公開(エクスポート)された識別子:
- 識別子の最初の文字が大文字の場合、その識別子はパッケージ外からも参照可能です。
- 他のパッケージから
パッケージ名.識別子の形式でアクセスできます。 - 関数、変数、定数、型などが該当します。
- 非公開(エクスポートされない)識別子:
- 識別子の最初の文字が小文字の場合、その識別子は宣言されたパッケージ内でのみ参照可能です。
- 他のパッケージからはアクセスできません。
- 特徴
- パッケージレベル(どの関数やブロックにも属さない)で宣言された識別子に適用されます。
- 同じパッケージ内のどのファイルからでもアクセス可能です。
- 例
// mypackage/some_file.go package mypackage import "fmt" const PublicConst = "公開定数" // パッケージ外からアクセス可能 var privateVar = 10 // パッケージ内でのみアクセス可能 func PublicFunction() { // パッケージ外からアクセス可能 fmt.Println("これは公開関数です。") fmt.Println("privateVar:", privateVar) // パッケージ内なのでアクセス可能 } func privateFunction() { // パッケージ内でのみアクセス可能 fmt.Println("これは非公開関数です。") }
// main.go (別のパッケージ) package main import ( "fmt" "your_module/mypackage" // mypackageをインポート ) func main() { fmt.Println(mypackage.PublicConst) // アクセス可能 mypackage.PublicFunction() // アクセス可能 // fmt.Println(mypackage.privateVar) // エラー: 非公開なのでアクセスできない // mypackage.privateFunction() // エラー: 非公開なのでアクセスできない }
3. ユニバース・スコープ (Universe Scope)
[編集]ユニバース・スコープは、Go言語全体でどこからでも参照可能な識別子に適用されます。これらはGo言語が事前に定義している組み込みの型、関数、定数などです。
- 例
- 組み込み型:
int,string,bool,float64,errorなど - 組み込み関数:
len(),cap(),make(),new(),append(),panic(),recover(),print(),println()など - 組み込み定数:
true,false,nil,iotaなど
これらの識別子は、どのパッケージやブロックからでも特別な宣言なしに利用できます。
スコープの優先順位
[編集]Goでは、スコープがネストされている場合、より内側のスコープで宣言された識別子が、外側のスコープで同じ名前の識別子が存在しても優先されます。これを「シャドーイング(shadowing)」と呼びます。
- 例
package main import "fmt" var name = "グローバル" // パッケージスコープ func main() { name := "ローカル" // main関数のブロックスコープ (シャドーイング) fmt.Println(name) // "ローカル" が出力される if true { name := "さらにローカル" // if文のブロックスコープ (さらにシャドーイング) fmt.Println(name) // "さらにローカル" が出力される } fmt.Println(name) // "ローカル" が出力される (ifブロックを抜けたため) }
まとめ
[編集]- ブロック・スコープ:
{}内で有効。最も限定的。 - パッケージ・スコープ: パッケージ内で有効。大文字で始まる識別子は公開され、小文字で始まる識別子は非公開。
- ユニバース・スコープ: Go言語全体で有効な組み込み識別子。
これらのスコープルールを理解することで、Goプログラムの可読性を高め、予期せぬ名前の衝突を避けることができます。