Go/条件分岐と繰り返し
制御構造
編集Goの構文がC言語と似ていると言われることがありますが、これは正しくありません。
GoとC言語の間には、構文や意味論において大きな違いがあります。「同様」や「似ている」といった表現では誤解を生む可能性があります。
条件分岐
編集Goでは、条件分岐をif文などで行いますが、C言語とは異なります。C言語にもif、else、switchなどがありますが、スコープルールなどに違いがあります。
if文
編集- C言語のif文
if (条件式) 文;
- Goのif文
if 条件式 { 文 }
Goでは条件式は真偽値である必要があり、i != 0 を単に i と書くことはできません。整数値と真偽値の間に自動変換はなく、キャストもできません。必ず比較演算子や論理演算子を使用します。
- コード例
package main import ( "fmt" "math" ) func main() { if num := math.NaN(); num < 0.0 { fmt.Println("負") } else if num > 0.0 { fmt.Println("正") } else if num == 0.0 { fmt.Println("零") } else { fmt.Println("NaN") } }
- 実行結果
NaN
Goでは、if文の条件式の前に「単純な文」を書くことが可能です。上記の例では、変数numがmath.NaN()で初期化されており、そのスコープはif文の中に限定されます。
Goには条件演算子(式 ? 値 : 値)はありません。条件演算子が必要な場合、if文を使うか、別の方法としてmapを活用することもできます。
- コード例
package main import ( "fmt" "unsafe" ) func main() { n := 0x5a5a5a5a5a5a5a5a size := int(unsafe.Sizeof(n)) * 8 m := map[bool]string{false: "●", true: "○"} for i := 0; i < size; i++ { fmt.Print(m[(1<<(size-i-1)&n) != 0]) } fmt.Println() }
- 実行結果
●○●○○●○●●○●○○●○●●○●○○●○●
switch文
編集switch文を使うと、複雑なif文を簡潔に表現できます。
- コード例
package main import ( "fmt" "math" ) func main() { switch num := math.NaN(); { case num < 0.0: fmt.Println("負") case num > 0.0: fmt.Println("正") case num == 0.0: fmt.Println("零") default: fmt.Println("NaN") } }
- 実行結果
NaN
Goのswitch文では、if文と同様に「単純な文」を書くことができます。C言語やJavaのようにbreak文は不要で、fallthrough文を使わない限り、自動的にcase節の終わりで処理が終了します。
select文
編集select文は、通信チャンネルを使った並行処理のための構文です。複数のチャンネルからの入力を待機し、その中で最初に準備ができたものを処理します。
- Select文を使ったタイムアウト
package main import ( "fmt" "time" ) func main() { done := make(chan bool) go func(s int) { fmt.Printf("#%d..do\n", s) time.Sleep(time.Duration(s) * time.Second) fmt.Printf("#%d..done\n", s) done <- true }(2) select { case <-done: fmt.Println("Done!") case <-time.After(1 * time.Second): fmt.Println("Timeout!") } }
- 実行結果
#2..do Timeout!
イテレート - for文
編集Goでは、for文が唯一の繰り返し構文です。Goにはdoやwhileは存在せず、for文のみで繰り返し処理を行います。
- 素朴なFor文
for i := 0; i < n; i++ { // 繰返す処理 }
C言語のfor文に似た形式ですが、Goのスコープルールが適用されます。
- Foreach的なFor文
for i, e := range collection { // 繰返す処理 }
この形式は、コレクション(スライスや配列、mapなど)を反復処理するために使います。C++の範囲for文やPythonのenumerate関数に似た使い方です。
素朴なFor文
編集素朴なfor文は、初期化、条件式、ポスト文で構成されます。
for 初期化; 条件式; ポスト文 { // 繰返す処理 }
条件式がfalseになるまで処理が繰り返されます。
For文の動きをif文とgoto文で表すと次のようになります。
{ 初期化 top: if !(条件式) { goto bottom } // 繰返す処理 ポスト文 goto top bottom: }