コンテンツにスキップ

Go/条件分岐と繰り返し

出典: フリー教科書『ウィキブックス(Wikibooks)』
< 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には条件演算子はありません

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:
}

脚註

[編集]