LoginSignup
7
3

More than 5 years have passed since last update.

当然知っているよね?Goの変数のスコープとシャドーウィングのクイズ

Last updated at Posted at 2018-06-24

Goにおける変数のスコープとシャドーウィングのクイズです。
本当に基本的な内容なのでGoを触っていたら楽楽全問正解できるはず!
実務的ではない、というか実務でこの状況に遭遇するのはまずい気がします。

問題は以下を省略してメイン関数だけ書いてます。

package main

import "fmt"

前提確認

var n = 0

func main() {
    fmt.Println(n)
}

出力は?

解答(折りたたみ)
0

これがわからなければ基本からやり直そう

第一問

var n = 0

func main() {
    n := 1
    fmt.Println(n)
}

出力は?

解答(折りたたみ)
1

まあこうなるよね。

第二問

var n = 0

func main() {
    n := 1
    fmt.Println(n)
    printN()
}

func printN() {
    fmt.Println(n)
}

出力は?

解答(折りたたみ)
1
0

main関数内のnはグローバル変数のnとは別の変数になります。スコープはメイン関数だけなので、printN関数の中ではグローバル変数が参照されます。

というわけで一行目が1で二行目が0。

第三問

func main() {
    n := 1
    {
        fmt.Println(n)
    }
}

出力は?

解答(折りたたみ)
1

中括弧のブロックはメイン関数の中なのでメイン関数で定義されたnを参照します。

第四問

func main() {
    n := 1
    {
        n := 2
        fmt.Println(n)
    }
    fmt.Println(n)
}

出力は?

解答(折りたたみ)
2
1

シンプルなシャドーウィングです。
中括弧で囲われたブロック内ではnは2、main関数ではnは1。

第五問

func main() {
    n := 1
    for n := n + 1; n < n+2; n++ {
        fmt.Println(n)
    }
}

出力は?
実行しないでください

解答(折りたたみ)
2
3
4
...

2以上の整数をえんえんと出力し続けます。
for文の条件式のうち、

n := n + 1 //左がforのスコープ、右がmainスコープ
n < n + 2 //両方forのスコープ
n++ //forのスコープ

n < n + 2は常に真なのでずっと出力が続きます。

最終問題

func main() {
    n := 1
    if n := n + 1; true {
        fmt.Println(n)
        n = n + 1
        fmt.Println(n)
    }
    fmt.Println(n)
}

出力は?

解答(折りたたみ)
2
3
1

軽く引っ掛けっぽい問題です。
if文の中のnは、if文だけのスコープになります。
それ故、5行目で書き換えてもmainスコープのnには影響を与えません。

終わりに

以上、いかがだったでしょうか?
ごくごく基本的なものだけ集めてみました。
真面目な話をすると、理由なく同じ変数名を別のスコープで使うのは可読性を下げるのでやめたほうがよいでしょう。

ありがとうございました!

7
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
3