制御構文一覧

【Go入門】Goの制御構文(1)~if文とfor文

こんにちは。Go入門ブログの第9回です。
本記事から2回にわたり、Goの基本的な制御構文を解説していきます。

今回は、制御文の中でも特に使用頻度の高いif文による条件分岐とfor文によるループ処理を解説します。
Goの制御構文は非常にシンプルであるため、理解は比較的容易かと思います。
ただし、Goならではといえる仕様や書き方もありますのでしっかり理解しておきましょう。

ifによる条件分岐

ifの基本構文

以下はもっとも基本的なifの構文です。

■ifの基本構文
if [条件式] {
条件に一致した場合の処理
}

他のプログラミング言語とほぼ同様ですので理解は容易だと思います。
留意点を挙げるとすれば、条件式を括弧で囲う必要がない一方で、Javaなどのように{ }を省略することができませんので注意してください。

elseによる複数条件の分岐

複数の条件を評価したい場合はelseを使用します。
これも他のプログラミング言語と大きくかわるところはないでしょう。

■elseによる複数条件の分岐
if [条件式A] {
条件Aに一致した場合の処理
} else if [条件式B] {
条件Bに一致した場合の処理
} else {
いずれの条件にも一致しない場合の処理
}

ここでサンプルをみてみましょう。
3の倍数なら”Fizz”、 5の倍数なら”Buzz”を出力するいわゆるFizzBuzzの例です。

package main

import "fmt"

func main() {
    FizzBuzz(15)
    FizzBuzz(18)
    FizzBuzz(20)
    FizzBuzz(22)
}

func FizzBuzz(i int) {

    if i%3 == 0 && i%5 == 0 {
        // 3の倍数かつ5の倍数なら"FizzBuzz"を出力
        fmt.Println("FizzBuzz")
    } else if i%3 == 0 {
        // 3の倍数なら"Fizz"を出力
        fmt.Println("Fizz")
    } else if i%5 == 0 {
        // 5の倍数なら"Buzz"を出力
        fmt.Println("Buzz")
    } else {
        // いずれの倍数でもなければ数値をそのまま出力
        fmt.Println(i)
    }

}

このサンプルの実行結果は以下のようになります。

$ go run main.go
FizzBuzz
Fizz
Buzz
22
簡易ステートメントの記述

ifステートメントの条件式の前に、簡易なステートメントを記述することができます。
この場合、セミコロンで区切って条件式の前に記述します。

■簡易ステートメントの記述
if [簡易ステートメント]; [条件式] {
条件に一致した場合の処理
}

簡易ステートメントで宣言された変数は、ifのスコープ内でのみ有効となります。
つまりこの簡易ステートメントは、条件の評価やifブロック内で使用する変数のスコープを制御するのに役立ちます。

実例を見てみましょう。

package main

import "fmt"

func main() {
   // ifの外で変数iを定義
   var i int = 5
   // ifの簡易ステートメントで変数iを定義
   if i := 2; i == 2{
      fmt.Println("ifスコープ内での変数i: ", i)
   }
   fmt.Println("ifスコープ外での変数i: ", i)
}

このサンプルの実行結果は以下のようになります。

$ go run main.go
ifスコープ内での変数i: 2
ifスコープ外での変数i: 5

このように、同名の変数iであっても、ifの外側で定義された場合と簡易ステートメントで定義された場合とでそれぞれ別の変数として扱われていることがわかります。
Goにおけるif文の特徴的な仕様であり、重要な機能でもありますのでぜひ使いこなしてください。

forループ

forの基本構文

forループの基本構文は、セミコロンで3つのステートメントに分けれられます。

■forループの基本構文
for 初期化; 条件式; 後処理 {
処理
}

初期化ステートメントは最初の繰り返し処理の前に実行されます。
ここでカウンタ変数の初期値を指定します。この変数はforステートメントのスコープ内でのみ有効です。

条件式ステートメントは毎回の繰り返し処理の実行前に評価されます。
条件式の評価がfalseとなった場合にループが停止されます。

後処理ステートメントは毎回の繰り返し処理の後に実行されます。
ここでカウンタ変数の更新をおこないます。

forの基本構文による繰り返し処理のサンプルをみてみましょう。

package main

import "fmt"

func main() {
    num := 0
    // 初期値0のカウンタ変数が10未満の間ループする
    for i := 0; i < 10; i++ {
        // 変数numにカウンタ変数を加算
        num += i
    }
    fmt.Println(num)
}

このサンプルの実行結果は以下のようになります。

$ go run main.go
45
ステートメントの省略

初期化、条件式、後処理の各ステートメントは省略可能です。
たとえば、先ほどの例の後処理を省略し、ループの中でカウンタ変数の更新を行うこともできます。

func main() {
    num := 0
    // カウンタ変数の省略
    for i := 0; i < 10; {
        // 変数numにカウンタ変数を加算
        num += i
        // カウンタ変数のインクリメント
        i++
    }
    fmt.Println(num)
}

for文に条件式のみを指定し、他の言語におけるwhile文のように記述することもできます。
この場合、セミコロン(;)を省略して記述できます。

func main() {
    num := 0
    i := 0
    // 範囲式のみを記述
    for i < 10 {
        num += i
        i++
    }
    fmt.Println(num)
}

すべてのステートメントを省略した場合、ループを終了する条件式がないため無限ループになります。

func main() {
    // すべてのステートメントを省略
    for {
        // 無限ループになる
    }
}
繰り返しの制御

ループ処理を制御する機能として、他の言語にもよくみられるbreakcontinueが使用できます。
breakステートメントが実行されると、それ以降の処理を実行せずにfor文のループを終了します。
continueステートメントが実行されると、それ以降の処理を実行せずに次のループを実行します。

package main

import "fmt"

func main() {
    var i int = 0;
    
    // ステートメントを省略したfor文(無限ループ)
    for {
       // 変数iのインクリメント
       i++
       if i > 100 {
         // 変数iが100を越えたらループを終了
         break
       } else if i % 2 == 1 {
         // 変数iが奇数の場合は後処理をスキップ
         continue
       }
       // 変数1を出力
       fmt.Print(i," ")
    }
}

このサンプルの実行結果は以下のようになります。

$ go run main.go
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 68 70 72 74 76 78 80 82 84 86 88 90 92 94 96 98 100

continueステートメントにより奇数は出力されず、偶数のみが出力されています。
また、100を越えた時点でbreakステートメントが実行され、ループが終了していることがわかります。

配列の全要素に対するループ

プログラミングにおいて、ループ処理により配列に含まれる全ての要素に対して処理を行いたいケースはよく発生します。
他のプログラミング言語ではfor eachがよく使用されますね。

このような場合、Goでは以下の構文を使用します。

■配列の全要素に対するループ
for [配列のインデックスを代入する変数],[配列の要素を代入する変数] = range [対象の配列] {
処理
}

このように、配列に対するループには予約語のrangeを使用します。
繰り返しごとに配列に含まれる要素が一つずつ処理され、インデックスと要素がステートメントで定義した変数に格納されて参照することができます。

さっそく実例をみてみましょう。

package main

import "fmt"

func main() {

    // 文字列型の配列を定義
    capitalArea := [7]string{"群馬", "栃木","埼玉", "東京", "神奈川", "千葉", "茨城"}

    // 配列の全要素を出力する
    for index, value := range capitalArea {
        fmt.Printf("首都圏%d: %s\n", index + 1, value)
    }
}

このサンプルの実行結果は以下のようになります。

$ go run main.go
首都圏1: 群馬
首都圏2: 栃木
首都圏3: 埼玉
首都圏4: 東京
首都圏5: 神奈川
首都圏6: 千葉
首都圏7: 茨城

変数indexに配列のインデックスが、valueに要素が代入さていることがわかると思います。
配列のインデックスは0から始まり、ループごとに1ずつ増分され、配列の要素数-1まで繰り返されています。

終わりに

本記事では、最も基本的な構文であるifとforについて解説しました。
Goの制御構文は意図的にシンプルに構成されています。
このため、複雑さはなく理解が比較的容易な一方で、他の言語とは少々違った特徴を持っていることも有りますので注意してください。

次回の記事では、ifとfor以外にGoでよく使用される重要な制御構文を解説します。


スポンサーリンク
スポンサーリンク
スポンサーリンク