言語バージョン 1.15.6

公開日 February 23, 2021, GMT+9

switch

このページでは豊富な例を用いてGolangのswitch文の使い方を学ぶことができます。

switch文は与えた式を元に条件分岐を実現するGolangの制御構文の1つです。

switchキーワードに式を指定し、その式が「switch文内に記述したcaseキーワードに指定した値」と一致する場合に該当のcaseブロック(case節)の処理が実行されます。
defaultキーワードを使用すると、どのcaseにも当てはまらない場合の処理を記述することができます。

注意事項として、一部のプログラミング言語でのswitch文と異なり、break文を使用しなくとも該当のcase節・default節の処理のみが実行されます。

// 記述例

switch{
  case1:
    // 式 == 値1となるときに実行される処理
  case2:
    // 式 == 値2となるときに実行される処理
  default:
    // どのcaseにも当てはまらない場合に実行される処理
}

TL;DR

基本

// 「switchに指定した値」と「caseに指定した値」が一致するブロックの処理が実行される
string1 := "Go"
switch string1 {
case "Golang":
  fmt.Println("case1")
case "Go":
  fmt.Println("case2")
default:
  fmt.Println("default")
}
==> case2






// どのcaseにも一致しないとdefaultのブロックが実行される
int2 := 100
switch int2 {
case 0:
case 1:
  fmt.Println("case2")
default:
  fmt.Println("default")
}
==> default






// どのcaseにも一致せずdefaultが無い場合は何も実行されない
int3 := 100
switch int3 {
case 0:
  fmt.Println("case1")
case 1:
  fmt.Println("case2")
}
==> 出力なし






// caseに複数の値を指定することもできる
switch 100 {
case 0, 1, 2:
  fmt.Println("case1")
case 100, 200:
  fmt.Println("case2")
}
==> case2






// 「switchに指定した型」と「caseに指定した型」に互換性がないとエラー
float4 := 3.14
switch float4 {
case 1.4:
  fmt.Println("case1")
case 100: // 100はfloatとしての100.0と扱われる
  fmt.Println("case2")
case "Go":
  fmt.Println("case3")
}
==> cannot use "Go" (type untyped string) as type float64

簡易文の記述

// switchには簡易文(simple statement)を指定することもできる
switch int1 := 1; int1 {
case 1:
  fmt.Println("case1")
case 2:
  fmt.Println("case2")
default:
  fmt.Println("default")
}
==> case1

caseに条件式を指定

// switchに何も指定しないとbool値を判定するようになる
int1 := 10
switch {
case int1 < 5:
  fmt.Println("case1")
case int1 == 5:
  fmt.Println("case2")
case int1 > 5:
  fmt.Println("case3")
default:
  fmt.Println("default")
}
==> case3






// 上記のswitch文は以下の記述と同じ
switch true {
case int1 < 5:
  fmt.Println("case1")
case int1 == 5:
  fmt.Println("case2")
case int1 > 5:
  fmt.Println("case3")
default:
  fmt.Println("default")
}
==> case3

fallthroughの指定

// fallthroughキーワードを使用すると次のブロックの処理も実行される
string1 := "A"
switch string1 {
case "A":
  fmt.Println("case1")
  fallthrough
case "B":
  fmt.Println("case2")
case "C":
  fmt.Println("case3")
default:
  fmt.Println("default")
}
==> case1
==> case2






// fallthroughキーワードを複数用いた場合
int2 := 1
switch int2 {
case 0:
  fmt.Println("case1")
case 1:
  fmt.Println("case2")
  fallthrough
case 2:
  fmt.Println("case3")
  fallthrough
default:
  fmt.Println("default")
}
==> case2
==> case3
==> default

型switch文

// 値ではなく型を場合分けに使用できる
var value1 interface{} = 0
switch value1.(type) {
case int:
  fmt.Println("case1")
case bool:
  fmt.Println("case2")
case float32:
  fmt.Println("case3")
default:
  fmt.Println("default")
}
==> case1






// switchに指定する型はinterface{}型でなければならない
value2 := "Go"
switch value2.(type) {
case string:
  fmt.Println("case1")
}
==> (エラー)cannot type switch on non-interface value value2 (type string)






// caseのブロックで変数を使う
var value3 interface{} = "Golang"
switch val := value3.(type) {
case int:
  fmt.Println("case1", val*val)
case string:
  fmt.Println("case2", val+"!!!")
}
==> case2 Golang!!!






// caseに複数の型を指定した場合、valはinterface{}型としてあつかわれるのでエラー
var value4 interface{} = "Golang"
switch val := value4.(type) {
case int, int8:
  fmt.Println("case1", val)
case string, bool:
  fmt.Println("case2", val + "!!!")
}
==> (エラー)invalid operation: val + "!!!" (mismatched types interface {} and string)

解説

// 記述例

switch{
  case1:
    // 式 == 値1となるときに実行される処理
  case2:
    // 式 == 値2となるときに実行される処理
  default:
    // どのcaseにも当てはまらない場合に実行される処理
}

基本

switch文は「switchキーワードに指定した式(値)」と、「caseキーワードに指定した値」が一致する場合にcase節(caseブロック)の処理が実行されます。
caseは複数指定することもできます。

記述したどのcaseにも当てはまらない場合、switch文の処理は実行されません。
defaultキーワードを使用すると「どのcaseにも当てはまらない場合に実行する処理」を記述することができます。

また、caseには,(カンマ)区切りで複数の値を指定することもできます。


注意事項が2つあります。

1つ目は、「caseに指定することができる値」は「switchに指定した式(値)の型と互換性のあるもの」しか指定できません。

2つ目は、Go言語のswitch文ではbreak文を指定せずとも一致したcase節の処理のみが実行されることです。
他の一部のプログラミング言語では、switch文を使用して条件分岐を行う際にcase節の最後にbreak文を指定しないと次のcase節、 default節の処理も続けて実行されてしまうといった仕様があります。
Go言語では異なりますので注意してください。

int1 := 1
switch int1 {
case 0:
  fmt.Println("case1")
case 1:
  fmt.Println("case2")
default:
  fmt.Println("default")
}
==> case2






// どのcaseの値にも当てはまらずdefaultがある場合
switch 1 {
case 0:
  fmt.Println("case1")
default:
  fmt.Println("default")
}
==> default






// どのcaseの値にも当てはまらずdefaultがない場合
switch 1 {
case 0:
  fmt.Println("case1")
case 2:
  fmt.Println("case2")
}
==> 出力なし






// caseに複数の値を指定
string3 := "go"
switch string3 {
case "string", "int":
  fmt.Println("case1")
case "golang", "go":
  fmt.Println("case2")
}
==> case2






// switchに指定した値と型の互換性が無い場合
int4 := 100
switch int4 {
case 6.0: // 6.0は6として扱われるのでOK
  fmt.Println("case1")
case "golang":
  fmt.Println("case2")
}
==> cannot use "golang" (type untyped string) as type int

簡易文の記述

switch文のswitchキーワードの後ろには、式だけでなく簡易文(simple statement)を記述することもできます。
簡易文を記述したい場合、式の前に;(セミコロン)区切りで簡易文を記述します。

この簡易文で変数を宣言・代入することで、switch文内でのみ有効な変数を定義することができます。(スコープがswitch文内の変数)
これはswitch文以外の処理部分へ影響を与えずに済むので、switch文内でのみ使用したい値は簡易文で定義することが推奨されます。

switch value := "golang"; value {
case "go":
  fmt.Println("case1")
case "golang":
  fmt.Println("case2")
default:
  fmt.Println("default")
}
==> case2

caseに条件式を指定

switchキーワードの後ろに式を記述しないこともできます。

この場合switch trueと記述された場合と同様になり、caseキーワードには条件式などbool値(真偽値)を返すものを指定できるようになります。

switch {
case "golang" == "golang":
  fmt.Println("case1")
case "go" == "golang":
  fmt.Println("case2")
default:
  fmt.Println("default")
}
==> case1






// 上記のswitch文は以下と同じ
switch true {
case "golang" == "golang":
  fmt.Println("case1")
case "go" == "golang":
  fmt.Println("case2")
default:
  fmt.Println("default")
}
==> case1

fallthroughの指定

Go言語では該当するcase節・default節の処理のみが実行されます。

fallthrough文を使用することで他のプログラミング言語にあるような、 「breakを記述しないと、次のcase文の処理も実行する挙動」を実現することができます。

int1 := 0
switch int1 {
case 0:
  fmt.Println("case1")
  fallthrough
case 1:
  fmt.Println("case2")
case 2:
  fmt.Println("case3")
default:
  fmt.Println("default")
}
==> case1
==> case2






// fallthroughキーワードを複数使用する場合
string2 := "B"
switch string2 {
case "A":
  fmt.Println("case1")
case "B":
  fmt.Println("case2")
  fallthrough
case "C":
  fmt.Println("case3")
  fallthrough
default:
  fmt.Println("default")
}
==> case2
==> case3
==> default

型switch文

通常switch文は指定された式の値をもとにして条件分岐を実行します。
しかし、指定する式を型アサーション(type assertion)に似た形式で指定すると、型をもとにした条件分岐を実装できます。
これは「型switch文(Type Switch)」とも呼ばれます。

対象となる値はinterface{}型である必要があり、型アサーションと異なり()丸括弧内にはtypeというキーワードを指定します。

また、通常のswitch文と同様にcaseに複数の型を指定することもできますが、 複数の型を使用しているcase節内では「該当の変数はinterface{}型として扱われる」ことに注意してください。

var value1 interface{} = "ABC"
switch value1.(type) {
case int:
  fmt.Println("case1")
case uint:
  fmt.Println("case2")
case string:
  fmt.Println("case3")
default:
  fmt.Println("default")
}
==> case3






// switchで指定する変数はinterface{}型である必要がある
value2 := 100
switch value2.(type) {
case string:
  fmt.Println("case1")
}
==> (エラー)cannot type switch on non-interface value value2 (type int)






// switch文内で変数を使用する
var value3 interface{} = 10
switch val := value3.(type) {
case int:
  fmt.Println("case1", val*val)
default:
  fmt.Println("default", val)
}
==> case1 100






// caseに複数の型を指定した場合はswitch文内でinterface{}型として扱われる
var value4 interface{} = 10
switch val := value4.(type) {
case int, int8, int64:
  fmt.Println("case1", val*val)
default:
  fmt.Println("default", val)
}
==> (エラー)invalid operation: val * val (operator * not defined on interface)

1次情報

Switch - Control structures - Effective Go - The Go Programming Language

Switch statements - The Go Programming Language Specification - The Go Programming Language

Switch - A Tour of Go

Type switches - A Tour of Go