第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' を出力しようとする
}