第6章 ブロックとスコープ
Go言語における「ブロック」と「スコープ」は、変数の可視性と生存期間を制御する重要な概念です。
ブロック
ブロックは、波括弧{}で囲まれたコードの領域です。関数本体、制御構造内部(if,for,switchなど)、または単純な波括弧によって形成されます。
スコープ
スコープは、変数が参照可能な範囲を指します。Go言語では、変数はその定義されたブロック内でのみアクセス可能で、外部からはアクセスできません(レキシカルスコープ)。
ローカルスコープ
関数内で宣言された変数は、その関数内でのみ参照可能です。
func myFunction() {
var a int = 10
fmt.Println(a) // 有効: aはこの関数内で定義されている
}
func main() {
myFunction()
fmt.Println(a) // エラー: aはこのスコープには存在しない
}
ループ内スコープ
forループ内で宣言された変数は、そのループ内でのみ有効です。
for i := 0; i < 5; i++ {
fmt.Println(i) // 有効: iはこのループ内で定義されている
}
fmt.Println(i) // エラー: iはこのスコープには存在しない
条件文内スコープ
if文などの条件文内で宣言された変数も、そのブロック内でのみ有効です。
if x := computeSomething(); x > 0 {
fmt.Println(x) // 有効: xはこのif文のスコープ内で定義されている
}
fmt.Println(x) // エラー: xはこのスコープには存在しない
グローバルスコープ
関数の外で宣言された変数は、同一パッケージ内の他のファイルからも参照可能です(グローバル変数)。
var globalVar int = 20
func main() {
fmt.Println(globalVar) // 有効: globalVarはグローバルスコープで定義されている
}
パッケージスコープ
パッケージスコープは、グローバル変数に似ていますが、同じパッケージ内でのみアクセス可能な変数を指します。これらの変数はパッケージのどのファイルからでもアクセスできますが、他のパッケージからは直接アクセスすることはできません。
package mypackage
var packageVar = "パッケージ内可視"
func MyFunction() {
// 'packageVar' は同一パッケージ内のどの関数からもアクセス可能
fmt.Println(packageVar)
}
ネストされたスコープ
Go言語では、スコープはネストすることができます。内側のスコープで宣言された変数は外側のスコープではアクセスできないが、外側のスコープで宣言された変数は内側のスコープからアクセス可能です。
var a = "外側"
func main() {
var b = "内側"
fmt.Println(a) // アクセス可能
fmt.Println(b) // アクセス可能
if true {
var c = "更に内側"
fmt.Println(a) // アクセス可能
fmt.Println(b) // アクセス可能
fmt.Println(c) // アクセス可能
}
fmt.Println(c) // アクセス不可、'c' は if 文のブロック内でのみ有効
}
練習問題1.
main関数の外にグローバル変数aを宣言し、main関数内でローカル変数aを宣言して、両方の変数の値を出力するGoプログラムを書いてください。
var a = "グローバル"
func main() {
var a = "ローカル"
// ここにコードを書く
}
練習問題2.
forループ内で変数iを宣言し、ループ内でその値を出力するGoプログラムを書いてください。その後、forループの外でiの値を出力しようとしてエラーが発生することを確認してください。
func main() {
// ここにコードを書く
// 'i' の値を出力しようとする
}
練習問題3.
if文内で変数xを宣言し、その変数を if文のブロック内でのみ出力するGoプログラムを書きなさい。また、ifブロックの外でxを出力しようとしてエラーが発生することを確認しなさい。
func main() {
if true {
var x = "可視"
// ここにコードを書く
}
// ここで 'x' を出力しようとする
}