Switch 文のナゾ(ってほどでもない)

2020/09/21に公開

いや,面白い tweet を見かけたので(解答も出てるからええやろ)。

見事に引っかかっちまったよ(笑)

実際に書いて実行してみれば分かる。

package main

func f() bool {
    return false
}

func main() {
    switch f()
    {
    case true:
        println(1)
    case false:
        println(0)
    }
}

試してみれば分かるが,実は 0 ではなく 1 が出力される。ポイントは switch 文の開始ブレスの位置である。

Go仕様書によると,式評価の switch 文は以下のように定義されている。

ExprSwitchStmt = "switch" [ SimpleStmt ";" ] [ Expression ] "{" { ExprCaseClause } "}" .
ExprCaseClause = ExprSwitchCase ":" StatementList .
ExprSwitchCase = "case" ExpressionList | "default" .

これを見ると switch トークンと開始ブレスの間に文と式を並べて記述できることが分かる。つまり上述のコードは

switch _ = f(); true {
case true:
    println(1)
case false:
    println(0)
}

と等価なのである。

なお最初のコードを整形ツールにかけると

package main

func f() bool {
    return false
}

func main() {
    switch f(); {
    case true:
        println(1)
    case false:
        println(0)
    }
}

と整形される。これなら分かりやすいよね。

というわけで Go のコードを書いたらこまめに整形して確認しましょう。まぁ,最近のエディタは自動で整形してくれるものもあるけど。

GitHubで編集を提案

Discussion