Ritolabo
  1. Home
  2. Golang
  3. GuideToBecomingGoDeveloper
  4. LearnTheBasics
  5. 条件文(Conditional Statements)- Golang learning step 1-9

条件文(Conditional Statements)- Golang learning step 1-9

  • 公開日
  • カテゴリ:LearnTheBasics
  • タグ:Golang,roadmap.sh,学習メモ
条件文(Conditional Statements)- Golang learning step 1-9

roadmap.sh > Go > Learn the Basics > Conditionals および if, switch statements の学習を進めていきます。

Conditionals と if, switch statements セクションは、同一の内容のため、まとめています。

学習箇所

※ 学習メモとしての記録ですが、後にこのセクションを学ぶ道しるべとなるよう、ですます調で記載しています。

contents

  1. 開発環境
  2. 条件文(Conditional Statements)
  3. if
    1. 基本的な構文
    2. 変数の宣言と使用
    3. 複数の条件
    4. if 文でのエラーハンドリングと不要な else 文の省略
  4. switch...case 文
    1. 基本的な構文
    2. 複数の条件
    3. 式を使用した case
    4. 型に対する switch
    5. fallthrough キーワード

開発環境

  • チップ: Apple M2 Pro
  • OS: macOS Sonoma
  • go version: go1.23.2 darwin/arm64

条件文(Conditional Statements)

条件文は、特定の条件が真である場合にのみコードを実行するために使用されます。Go は以下の条件文をサポートしています。

  • if 文
  • if...else 文
  • switch...case 文

参考リソース:

if

基本的な構文

Go の if 文は、次のように書くことができます。

if 条件 {
    // 条件が true の場合に実行されるコード
}

括弧 () は不要です。中括弧 {} は省略できません。

例えば、変数 x が 10 より大きい場合にメッセージを出力する場合は次のようになります。

package main

import "fmt"

func main() {
  x := 15
  if x > 10 {
    fmt.Println("x is greater than 10")
  }
}

else if と else の使用

if に加えて、else if や else を使用して、複数の条件を処理することも可能です。

x := 7
if x > 10 {
  fmt.Println("x is greater than 10")
} else if x == 10 {
  fmt.Println("x is equal to 10")
} else {
  fmt.Println("x is less than 10")
}

変数の宣言と使用

Go の if 文では、条件を評価する前に変数を宣言することができます。この変数は if 文のスコープ内でのみ有効です。

if y := 20; y > 10 {
  fmt.Println("y is greater than 10")
}

ここで、y は if 文内でのみ使える一時的な変数として定義されています。この書き方により、スコープを狭めることで変数の影響範囲を限定し、コードを整理できます。

複数の条件

Go では、if 文の中で複数の条件を &&(AND)や ||(OR)演算子を使って組み合わせることもできます。

a := 5
b := 8
if a < 10 && b > 5 {
   fmt.Println("Both conditions are true")
}
a := 5
b := 0
if a == 0 || b == 0 {
   fmt.Println("a or b is 0.")
}

if 文でのエラーハンドリングと不要な else 文の省略

if 文のブロックが break、continue、goto、あるいは return で終了する場合、不要な else 文は省略することが推奨されています。これは、Go のコードを簡潔で読みやすく保つための一般的なスタイルです。

次の例を見てみましょう

package main

import (
  "errors"
  "fmt"
)

func checkNumber(n int) error {
  if n < 0 {
    return errors.New("negative number not allowed")
  }
  if n == 0 {
    return errors.New("zero is not a valid number")
  }
  fmt.Println("Valid number:", n)
  return nil
}

func main() {
  n := 10
  err := checkNumber(n)

  if err != nil {
    fmt.Println("Error:", err)
    return
  }

  fmt.Println(n)
}

このコードは、数値をチェックし、0 ないし負の数だった場合はエラーを返しています。成功した場合には数値を出力するという後続の処理が実行されます。

エラーチェックを行う際、エラーが発生した場合は return で早期に処理を終了するため、エラーハンドリングの後に else 文を使う必要がなくなります。これにより、コードのフローがスムーズにページの下方向に進み、エラー処理が適宜排除されるという利点があります。また、エラーハンドリングを早期に行うことで、後続の処理が簡潔で見やすくもなります。

switch...case 文

基本的な構文

Go の switch は次のような構文になります。

switch value {
case 1:
   fmt.Println("Value is 1")
case 2:
   fmt.Println("Value is 2")
default:
   fmt.Println("Value is neither 1 nor 2")
}

この例では、value の値に応じて case の処理が実行され、どの case にも一致しない場合は default が実行されます。

Go の switch は if...else よりも効率的な分岐処理を行うことができます。特に、1 度だけ評価される式に基づいて分岐が決定されるため、複数の条件を評価する際に無駄な再評価を避けることができます。これは、複雑な条件分岐を扱う際に有効です。

他の言語では case の後に break を書かないと次の case にも処理が流れてしまうことが多いですが、Go では各 case の最後に自動的に break が入ります。そのため、明示的に break を書く必要はありません。

複数の条件

Go の switch では、1つの case で複数の値を指定することができます。これにより、条件分岐をより簡潔に記述することが可能です。

switch value {
case 1, 3, 5:
   fmt.Println("Value is odd")
case 2, 4, 6:
   fmt.Println("Value is even")
default:
   fmt.Println("Value is unknown")
}

この例では、1 つの case で複数の値(1,3,5 や 2,4,6)を指定しています。switch 文を使用することで、if...else 文と比較して条件が多い場合でもコードがすっきりとまとまり、可読性が向上します。

switch は複雑な条件分岐を効率的に処理でき、特に条件の数が多い場合には if...else よりも効率的です。また、Go の switch では各 case の後に自動的に break が含まれているため、明示的に break を記述する必要がなく、不要なコードを省けます。

式を使用した case

Go の switch 文では、switch キーワードの直後に渡す評価対象を省略し、各 case で直接式を使用することができます。これにより、より柔軟で表現力豊かな条件分岐が可能になります。

この方法では、switch キーワード直後の評価対象を省略し、各 case で条件式を直接記述します。

switch {
case condition1:
    // 処理1
case condition2:
    // 処理2
default:
    // デフォルトの処理
}

以下は、現在時刻に基づいて異なるメッセージを表示する例です。

package main

import (
	"fmt"
	"time"
)

func main() {
	t := time.Now()
	switch {
	case t.Hour() < 12:
		fmt.Println("午前中です")
	case t.Hour() < 17:
		fmt.Println("午後です")
	case t.Hour() < 19:
		fmt.Println("夕方です")
	default:
		fmt.Println("夜です")
	}
}

この例では、switch の後に評価対象がなく、各 case で直接 t.Hour() を使用した条件式を記述しています。これにより、時間帯に応じて適切なメッセージを表示することができます。

このアプローチは、複雑な条件分岐を必要とする場合や、複数の if...else 文を置き換えたい場合に特に有用です。コードの可読性を向上させ、論理的な流れをより明確に表現することができます。

型に対する switch

Go では、型に基づいて分岐することも可能です。これは特にインターフェースを使ったプログラミングで役立ちます。

var x interface{} = "Hello"
switch v := x.(type) {
case int:
   fmt.Println("x is an int:", v)
case string:
   fmt.Println("x is a string:", v)
default:
   fmt.Println("x is of a different type")
}

fallthrough キーワード

Go の switch 文には他の言語とは異なる特徴として、fallthrough というキーワードが存在します。fallthrough は、ある case の処理が終わった後も、次の case の処理を強制的に実行するために使います。

通常、Go の switch 文では各 case に自動的に break が入っており、1つの case が実行されるとそれ以上の case が実行されることはありません。しかし、fallthrough を使用することで、次の case も続けて実行させることが可能になります。

package main

import "fmt"

func main() {
  switch value := 2; value {
  case 1:
    fmt.Println("Case 1")
  case 2:
    fmt.Println("Case 2")
    fallthrough
  case 3:
    fmt.Println("Case 3")
  default:
    fmt.Println("Default case")
  }
  // => Case 2
  // => Case 3
}

この例では、value が 2 のため、2 つ目の case がまず出力されます。その後、fallthrough によって 3 つ目の case も続けて実行され、出力されます。

特徴と注意点

fallthrough は、case の条件に関係なく次の case を実行します。これは、「次の case の条件が成り立っているかどうか」に関わらず動作します。例えば、以下のような場合でも 3 つ目の case が実行されます。

switch value := 2; value {
case 1:
   fmt.Println("Case 1")
case 2:
   fmt.Println("Case 2")
   fallthrough
case 4:
   fmt.Println("Case 4") // value は 4 ではないが、fallthrough で実行される
default:
   fmt.Println("Default case")
}
// => Case 2
// => Case 4
最後の case では使えない

fallthrough は、switch 文の最後の case では使用できません。なぜなら、次に実行すべき case が存在しないためです。

意図的な連続処理に使う

fallthrough は条件に基づく厳密な分岐処理を行うためのものではなく、意図的に連続して処理を実行したい場合に使います。if...else で厳密な条件分岐を行いたい場合には、fallthrough は適していません。

使いどころ

fallthrough は、次のような場合に役立つことがあります。

段階的な処理の実行

例えば、特定のランクに応じた複数の特典を段階的に実行したい場合などです。

rank := 2
switch rank {
case 1:
   fmt.Println("Rank 1 benefits")
   fallthrough
case 2:
   fmt.Println("Rank 2 benefits")
   fallthrough
case 3:
   fmt.Println("Rank 3 benefits")
}
// => Rank 2 benefits
// => Rank 3 benefits

この例では、ランクが 2 の場合、「Rank 2 benefits」と「Rank 3 benefits」の両方が実行されます。

なお、fallthrough は慎重に使用する必要があります。case の条件が無視されるため、意図しない動作を避けるために、特定の状況でのみ使うことが推奨されます。

まとめ

  • Go 言語は主に 3 つの条件文をサポート
    • if 文
    • if...else 文
    • switch...case 文
  • if 文
    • 括弧()は不要、中括弧{}は省略不可
    • 条件評価前に変数宣言が可能
    • &&(AND)や||(OR)を使用して複数条件の組み合わせが可能
    • エラーハンドリングでは早期 return を使用し、不要な else 文を省略することが推奨
  • switch 文
    • 自動的に break が挿入されるため、明示的な break は不要
    • 1つの case で複数の値を指定可能
    • 式を使用した case で柔軟な条件分岐が可能
    • 型に対する switch も可能
    • fallthrough キーワードを使用して次の case も実行可能(ただし慎重に使用する必要あり)
  • 条件文の選択:
    • 単純な条件分岐には if 文
    • 複雑な条件や多数の分岐には switch 文が効率的
    • 型に基づく分岐が必要な場合は switch の型アサーションを使用


[Next] Step 1-10: for 文(For Loop)

[Prev] Step 1-8: 関数(Functions)

Author

rito

rito

  • Backend Engineer
  • Tokyo, Japan
  • PHP 5 技術者認定上級試験 認定者
  • 統計検定 3 級