[Goのはじめ方] Part7: 制御構文(if, for, switch)

プログラムは通常、上から下へと順番に実行されますが、時には条件によって処理を変えたり、同じ処理を繰り返したりする必要があります。Go言語では、そのような制御を行うために if文、for文、switch文が用意されています。これらを使いこなして、より柔軟なプログラムを作成しましょう!

if文:条件による分岐

if文は、指定した条件が真 (true) か偽 (false) かによって、実行する処理を分岐させます。

基本的なif文

条件式が true の場合に、続くブロック { } 内の処理を実行します。

package main
import "fmt"
func main() {	score := 85	if score > 80 {	fmt.Println("素晴らしい!合格です! ") // score > 80 が true なので実行される	}
}

if-else文

条件式が true の場合と false の場合で、それぞれ異なる処理を実行します。

package main
import "fmt"
func main() {	age := 18	if age >= 20 {	fmt.Println("成人です。")	} else {	fmt.Println("未成年です。") // age >= 20 が false なのでこちらが実行される	}
}

if-else if-else文

複数の条件で分岐させたい場合に使用します。

package main
import "fmt"
func main() {	score := 75	if score >= 90 {	fmt.Println("優")	} else if score >= 80 {	fmt.Println("良")	} else if score >= 70 {	fmt.Println("可") // score >= 70 が true なのでこちらが実行される	} else {	fmt.Println("不可")	}
}

簡易ステートメント付きif文

Goの特徴的な書き方として、if の条件式の前に簡単なステートメント(通常は変数宣言と初期化)を書くことができます。ここで宣言された変数のスコープ(有効範囲)は、if 文とその else if / else ブロック内に限定されます。これはコードを簡潔にし、変数の影響範囲を狭めるのに役立ちます。

package main
import (	"fmt"	"math/rand"	"time"
)
func main() {	// Go 1.20 より前では Seed の設定が推奨されていました	// rand.Seed(time.Now().UnixNano())	// 簡易ステートメントで乱数を生成し、その値で分岐	if n := rand.Intn(10); n > 5 {	fmt.Printf("%d は 5 より大きい\n", n)	// 変数 n はこの if ブロック内でのみ有効	} else {	fmt.Printf("%d は 5 以下\n", n)	// 変数 n はこの else ブロック内でのみ有効	}	// fmt.Println(n) // ここでは n は使えない (スコープ外)
}
ポイント: 簡易ステートメントで宣言された変数のスコープは if (および関連する else if/else) ブロック内に限定されます。

for文:繰り返し処理

Go言語の繰り返し処理は for文のみで表現されます。他の言語にある whiledo-while に相当する構文はありませんが、for文の柔軟な書き方でそれらを表現できます。

基本形 (C言語スタイル)

初期化ステートメント、条件式、後処理ステートメントを指定します。

package main
import "fmt"
func main() {	sum := 0	// 1から10までの合計を計算	for i := 1; i <= 10; i++ { // 初期化; 条件; 後処理	sum += i	}	fmt.Println("合計:", sum) // 合計: 55
}

条件のみ (whileスタイル)

条件式のみを指定すると、その条件が true である間、繰り返し処理を実行します。

package main
import "fmt"
func main() {	n := 1	// nが100未満の間、2倍し続ける	for n < 100 {	n *= 2	}	fmt.Println("結果:", n) // 結果: 128
}

無限ループ

条件式を省略すると無限ループになります。ループを抜けるには break 文を使用します。

package main
import (	"fmt"	"time"
)
func main() {	count := 0	for { // 無限ループ	fmt.Println("ループ中...")	time.Sleep(500 * time.Millisecond)	count++	if count >= 3 {	fmt.Println("ループを抜けます。")	break // countが3以上になったらループを終了	}	}
}

ループ内の特定の回の残りの処理をスキップして次のイテレーションに進むには continue 文を使用します。

for range ループ

スライス、配列、マップ、文字列、チャンネルなど、反復可能なデータ構造の要素を順番に取り出すのに便利です。

package main
import "fmt"
func main() {	// スライスの例	nums := []int{10, 20, 30}	sum := 0	// インデックス(i)と値(num)を取得	for i, num := range nums {	fmt.Printf("インデックス: %d, 値: %d\n", i, num)	sum += num	}	fmt.Println("スライスの合計:", sum)	// 値だけ必要な場合 (インデックスを無視)	sum = 0	for _, num := range nums { // インデックスを _ で破棄	sum += num	}	fmt.Println("スライスの合計 (値のみ):", sum)	// マップの例	kvs := map[string]string{"a": "Apple", "b": "Banana"}	// キー(k)と値(v)を取得	for k, v := range kvs {	fmt.Printf("%s -> %s\n", k, v)	}	// キーだけ必要な場合	for k := range kvs {	fmt.Println("キー:", k)	}	// 文字列の例 (rune単位で反復)	for i, r := range "Go言語" {	fmt.Printf("%d: %c\n", i, r) // iはバイト単位のインデックス, rはrune(文字)	}
}
注意 (Go 1.22以降): 以前のGoバージョンでは、for rangeループ内で取得した変数はループ全体で同じメモリアドレスを指していましたが、Go 1.22からは各イテレーションで新しい変数が作られるように挙動が変更されました。これにより、ループ変数を使ったゴルーチンなどでの意図しないバグが起こりにくくなりました。初学者の段階では大きな影響はないかもしれませんが、知っておくと良いでしょう。

switch文:多岐分岐

switch文は、ある式の値に基づいて、複数の処理経路から一つを選んで実行します。if-else if を重ねるよりも簡潔に書ける場合があります。Goの switch は、一致した case の処理が終わると自動的に switch 文を抜けます(暗黙の break)。

基本的なswitch文

package main
import "fmt"
func main() {	signal := "red"	switch signal {	case "red":	fmt.Println("止まれ ")	case "yellow":	fmt.Println("注意 ")	case "blue", "green": // 複数の値をまとめることも可能	fmt.Println("進め ")	default: // どの case にも一致しない場合	fmt.Println("不明な信号")	}
}

fallthrough

Goでは通常、case の終わりに暗黙的な break がありますが、意図的に次の case の処理も実行したい場合は fallthrough キーワードを使用します。ただし、fallthrough の使用はコードを読みにくくすることがあるため、慎重に使いましょう。

package main
import "fmt"
func main() {	num := 2	switch num {	case 1:	fmt.Println("1")	fallthrough // 次のcaseも実行	case 2:	fmt.Println("2") // ここが実行される	fallthrough // さらに次のcaseも実行	case 3:	fmt.Println("3") // ここも実行される	default:	fmt.Println("default")	}	// 出力:	// 2	// 3
}

式なしswitch (switch true)

switch の後に式を書かない場合、switch true と同じ意味になり、各 case に書かれた条件式を上から順に評価し、最初に true になった case の処理を実行します。これは複雑な if-else if-else 文をよりきれいに書く方法として使えます。

package main
import "fmt"
func main() {	score := 88	switch { // 式を省略 (switch true と同じ)	case score >= 90:	fmt.Println("優")	case score >= 80:	fmt.Println("良") // ここが true になるので実行される	case score >= 70:	fmt.Println("可")	default:	fmt.Println("不可")	}
}
ヒント: 式なし switch は、条件分岐が複数ある場合にコードを読みやすくするのに役立ちます。

まとめ

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です