Go言語で効率的かつ読みやすいコードを書くために、条件分岐の最適化は避けて通れないテーマです。

特に、複数の条件に対して同じ処理を実行したい場合、if-else文を重ねるよりも switch 文を適切に活用する方がスマートに記述できます。

本記事では、Go言語の switch 文における複数条件の指定方法を中心に、現場で役立つ実践的なテクニックを詳しく解説します。

コードの冗長さを減らし、メンテナンス性の高いプログラムを実装するための知識を深めていきましょう。

Go言語におけるswitch文の基本構造

Go言語の switch 文は、他のC系言語と比較して非常に強力で柔軟な設計がなされています。

最も大きな特徴の一つは、各caseの最後に自動的に break が挿入されるという点です。

これにより、意図しないフォールスルー(次のcaseへの流入)を防ぐことができ、バグの混入を最小限に抑えることが可能です。

まずは、基本的な単一条件の switch 文の書き方をおさらいしましょう。

Go
package main

import "fmt"

func main() {
    day := "Monday"

    switch day {
    case "Monday":
        fmt.Println("週の始まりです")
    case "Friday":
        fmt.Println("週末まであと少しです")
    default:
        fmt.Println("通常業務の日です")
    }
}
実行結果
週の始まりです

このように、特定の変数に対して一つの値を評価するのが基本の形です。

しかし、実際の開発現場では「月曜日と水曜日と金曜日は同じ処理をしたい」といった、一つのcaseに対して複数の条件を割り当てたい場面が多く存在します。

複数条件を指定する「カンマ区切り」の活用

Go言語で一つの case に複数の条件を指定する場合、値をカンマ , で区切って記述するのが最もシンプルで推奨される方法です。

他の言語で見られるような「caseを縦に並べる」必要はなく、一行で簡潔に記述できる点がGoの魅力です。

カンマ区切りの基本構文

カンマ区切りを使用することで、論理和(OR条件)として評価されるようになります。

以下の例では、土曜日と日曜日の場合に「休日」と表示する処理をまとめています。

Go
package main

import "fmt"

func checkDayType(day string) {
    switch day {
    case "Saturday", "Sunday":
        // 土曜日または日曜日の場合に実行される
        fmt.Printf("%s は休日です\n", day)
    case "Monday", "Tuesday", "Wednesday", "Thursday", "Friday":
        // 平日の場合に実行される
        fmt.Printf("%s は平日です\n", day)
    default:
        fmt.Println("不明な曜日です")
    }
}

func main() {
    checkDayType("Sunday")
    checkDayType("Wednesday")
}
実行結果
Sunday は休日です
Wednesday は平日です

この書き方を採用することで、同じ実行コードを何度も記述する手間が省け、コードの可読性が飛躍的に向上します。

カンマ区切りのメリット

カンマ区切りによる複数条件指定には、主に3つのメリットがあります。

  • コードの圧縮: 重複するコードが排除され、一目で何が同じグループなのかが判明します。
  • メンテナンス性: 条件を増やしたい場合に、カンマの後に値を追加するだけで済みます。
  • 意図の明確化: 「これらの値は同じロジックで処理する」というプログラマの意図が明確に伝わります。

式を省略したswitch文による複雑な条件分岐

Go言語の switch 文では、 switch の直後に評価対象の変数を記述しない「式なしのswitch」という書き方が可能です。

この場合、各 case には bool 型を返す任意の式を記述できるようになります。

これは、実質的に if-else if 文のよりクリーンな代替案として機能します。

数値範囲や論理演算を組み合わせる

カンマ区切りだけでは対応できない「10以上100以下」といった範囲指定や、複数の変数を組み合わせた条件も switch で綺麗に書けます。

Go
package main

import "fmt"

func evaluateScore(score int) {
    switch {
    case score >= 90:
        fmt.Println("優秀です")
    case score >= 70, score < 90 && score >= 60:
        // 70点以上、または「60点以上90点未満」の特定の条件をカバー
        // ※実際には範囲が重なっていますが、カンマで複数式を書ける例です
        fmt.Println("合格圏内です")
    case score < 60:
        fmt.Println("再試験が必要です")
    }
}

func main() {
    evaluateScore(95)
    evaluateScore(75)
    evaluateScore(45)
}

式なしの switch では、最初に true と評価された case のみが実行されるというルールを覚えておきましょう。

fallthrough を使った連続実行の制御

Go言語の switch はデフォルトで break しますが、あえて次の case の処理も実行したい場合には fallthrough キーワードを使用します。

ただし、複数条件を扱う文脈では、カンマ区切りの方が圧倒的に安全で読みやすいため、 fallthrough の多用は避けるべきです。

fallthrough の挙動と注意点

fallthrough は、次のcaseの条件式が true かどうかに関わらず、強制的にそのブロックを実行するという性質を持っています。

Go
package main

import "fmt"

func stepProcess(step int) {
    switch step {
    case 1:
        fmt.Println("ステップ1を開始")
        fallthrough
    case 2:
        fmt.Println("ステップ2を継続")
        fallthrough
    case 3:
        fmt.Println("最終処理を完了")
    }
}

func main() {
    stepProcess(1)
}
実行結果
ステップ1を開始
ステップ2を継続
最終処理を完了

この挙動は非常に特殊であるため、「特定の状態から順次処理を流したい」という明確な設計意図がある場合に限定して使用してください。

単に「AまたはBのときに同じ処理をしたい」という目的であれば、必ず case A, B: というカンマ区切りの形式を選びましょう。

Type Switchにおける複数型指定

Go言語の強力な機能の一つに、インターフェースの動的な型を判定する type switch があります。

ここでも、複数の型をまとめて扱うためにカンマ区切りを利用することが可能です。

Go
package main

import "fmt"

func identifyType(i interface{}) {
    switch v := i.(type) {
    case int, int32, int64:
        fmt.Printf("整数型です: %v\n", v)
    case string:
        fmt.Printf("文字列です: %s\n", v)
    case bool:
        fmt.Printf("論理値です: %t\n", v)
    default:
        fmt.Println("未知の型です")
    }
}

func main() {
    identifyType(42)
    identifyType("Hello Go")
    identifyType(true)
}

上記のように int, int32, int64 と並べることで、似たような性質を持つ異なる型を一括で処理できるようになります。

これは、ジェネリクスが導入された後のGoにおいても、インターフェースを介した柔軟なプログラミングにおいて非常に有用なテクニックです。

switch文で複数条件を扱う際のベストプラクティス

効率的な条件分岐を記述するためのベストプラクティスをいくつか紹介します。

1. 優先順位が高い順にcaseを並べる

式なしの switch を使う場合、条件は上から順に評価されます。

より具体的、あるいは頻度が高い条件を上に配置することで、評価回数を減らし、パフォーマンスと可読性を両立させることができます。

2. defaultを必ず含める

全ての条件を網羅しているつもりでも、将来的な仕様変更で新しい値が追加される可能性があります。

予期しない挙動を防ぐために、エラーハンドリングやログ出力を行う default 句を記述する習慣をつけましょう。

3. case内を長くしすぎない

一つの case ブロックに数十行のコードを記述すると、全体の構造が見えにくくなります。

処理が複雑になる場合は、その処理を独立した関数に切り出し、 case 内では関数を呼び出すだけにするのが理想的です。

実戦例:HTTPステータスコードの分類

最後に、実際の開発でよく見られる「HTTPステータスコードの分類」を switch で実装してみましょう。

Go
package main

import "fmt"

func categorizeStatus(code int) {
    switch {
    case code >= 200 && code < 300:
        fmt.Println("Success (成功)")
    case code == 400, code == 401, code == 403, code == 404:
        fmt.Println("Client Error (クライアントエラー)")
    case code >= 500:
        fmt.Println("Server Error (サーバーエラー)")
    default:
        fmt.Println("Other Status (その他)")
    }
}

func main() {
    categorizeStatus(200)
    categorizeStatus(404)
    categorizeStatus(503)
}

このように、範囲指定と特定の個別値(カンマ区切り)を適宜使い分けることで、ビジネスロジックが非常にスッキリと整理されます。

まとめ

Go言語の switch 文は、単なる値の分岐以上の柔軟性を持った構文です。

特に case A, B: のようなカンマ区切りによる複数条件指定は、コードの重複を避け、簡潔な記述を実現するための基本テクニックです。

また、複雑なロジックが必要な場合は「式なしの switch 」を活用し、型判定が必要な場合は type switch を使うことで、あらゆる条件分岐に対応できます。

フォールスルーの挙動を正しく理解し、 default を適切に配置することで、堅牢なプログラムを構築してください。

今回紹介したテクニックを駆使して、よりクリーンでメンテナンスしやすいGoコードを目指しましょう。