Go言語の switch 文
ここでは Go 言語の switch 文について説明します。
Go の switch 文の基本
switch 文はある値を評価して、その値ごとに処理を分岐させるために使います。
条件による分岐という意味では、if 文でも同様の処理の分岐を行うことは可能です。しかし通常、 たくさんの分岐があり、それぞれの分岐毎の処理が少ない場合などに、switch 文が使われます。
switch 文の基本的な使い方は次の通りです。
switch m {
case 0:
// m が 0 の時
case 1:
// m が 1 の時
default:
// その他の場合
}
switch というキーワードに続けて、評価対象となる変数を指定します。この場合変数 m の値によって処理が分岐します。 m の値が case キーワードに続く値の場合に、そのセクションが実行されます。例えば m の値が 0 である場合は、 case 0: から始まる箇所が実行されます。
他の言語で多くみられるような、case の処理を区切る break は不要です。Go では既定でフォールスルーしません。
default: はいずれの case にも該当しない場合に実行されます。 default は任意です。なくても構いません。
それでは、次の例を見てみましょう。次の例を実行するとどのような出力になるでしょうか。
ここでは for 文で変数 m に値を 0 から 8 まで順に渡し、 switch 文の処理を繰り返しています。
package main
import (
"fmt"
)
func main() {
for m := 0; m < 9; m++ {
switch m {
case 0, 1, 2: // 値を複数指定
fmt.Println("A", m)
case 3: // 実行する箇所を持たない
case 4:
fmt.Println("B", m)
case 5:
fallthrough // 次の case にフォールスルーする
case 6:
fmt.Println("C", m)
case 7:
fmt.Println("D", m)
fallthrough
case 8:
fmt.Println("E", m)
}
}
}
実行結果は次のようになります。
go run main.go
A 0
A 1
A 2
B 4
C 5
C 6
D 7
E 7
E 8
コードの内容を説明します。
10行目では case ラベルに複数の値を指定しています。
case 0, 1, 2: // 値を複数指定
fmt.Println("A", m)
この場合、変数 m が値 0, 1, 2 のいずれかの時に A という文字が出力されます。
次に case 3: では処理する内容が記述されていません。
case 3: // 実行する箇所を持たない
case 4:
fmt.Println("B", m)
この場合は m が 3 という値の場合は何もしません。
一方、 case 5: では fallthrough キーワードを使い、次の case にフォールスルーしています。
case 5:
fallthrough // 次の case にフォールスルーする
case 6:
fmt.Println("C", m)
従ってこの場合 m の値が 5 の場合と 6 の場合に C という文字が出力されます。
次の箇所のように、何か処理をしてからフォールスルーすることもできます。
case 7:
fmt.Println("D", m)
fallthrough
case 8:
fmt.Println("E", m)
Go の switch 内スコープの変数
次の例では rand.Intn(3) 関数で 0 から 2 までの値を取る乱数を生成して、それを変数 m に格納。 switch 文では m の値で条件分岐しています。
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
rand.Seed(time.Now().UnixNano()) // 乱数のシード
m := rand.Intn(3) // 0 から 2 までの乱数を生成
switch m {
case 0:
fmt.Println("Zero")
case 1:
fmt.Println("One")
case 2:
fmt.Println("Two")
}
}
ここでは m の値が 0, 1, 2 のときにそれぞれ、 Zero、 One、Two という文字を出力しています。
このとき、変数 m を switch の外で使わないのであれば、次のように switch キーワードの後に変数の宣言をすることが可能です。
switch m := rand.Intn(3); m { // ここで宣言
case 0:
fmt.Println("Zero")
case 1:
fmt.Println("One")
case 2:
fmt.Println("Two")
}
変数の宣言文をセミコロン ; で終了して、その次に switch による評価対象となる変数を記載します。
Go の switch で case に条件式を使う
Go の switch では case に続いて、条件式を記述できます。
m := rand.Intn(10)
switch {
case m < 5:
fmt.Println("Less than 5")
case m == 5:
fmt.Println("Equal to 5")
case m > 5:
fmt.Println("Greater than 5")
}
この場合、switch 文にて変数を指定しません。 switch キーワードの後空白のあとすぐに { となっています。
switch 文で宣言する変数がある場合には、 宣言文の終わりにセミコロンを記述し、そのあとは空白のままにします。
switch m := rand.Intn(10); {
case m < 5:
fmt.Println("Less than 5")
case m == 5:
fmt.Println("Equal to 5")
case m > 5:
fmt.Println("Greater than 5")
}
Go の switch での暗黙的なブロック
Go の switch 文で、case に続く箇所は暗黙的なブロックとして認識されます。
このため、次のように case 毎のスコープとして変数を宣言できます。
package main
import (
"fmt"
"math/rand"
)
func main() {
i := 100 // switch の外で宣言
fmt.Println("A", i)
switch m := rand.Intn(10); {
case m < 5:
i := 10 // case 毎に宣言可
fmt.Println("[1]", i)
case m == 5:
i := 20 // case 毎に宣言可
fmt.Println("[2]", i)
case m > 5:
i := 30 // case 毎に宣言可
fmt.Println("[3]", i)
}
fmt.Println("B", i)
}
実行例は次の通りです。
go run main.go
A 100
[1] 10
B 100
9行目で変数 i を宣言し、値 100 で初期化。 さらに switch 文内部で 13, 16, 19 行目でそれぞれ別の変数 i を宣言しています。これらは全て別の変数として扱われます。