チュートリアル

Go基礎:条件分岐とループ

Go入門制御構文
広告エリア

条件分岐

if文

age := 20

if age >= 20 {
    fmt.Println("成人です")
} else if age >= 13 {
    fmt.Println("ティーンエイジャーです")
} else {
    fmt.Println("子供です")
}

if文の初期化文

// 変数宣言をif文に含める
if age := getAge(); age >= 20 {
    fmt.Println("成人です")
} else {
    fmt.Println("未成年です")
}
// age はこのスコープ外では使用不可

// エラーチェックでよく使用
if err := doSomething(); err != nil {
    fmt.Println("エラー:", err)
    return
}

switch文

day := 3

switch day {
case 1:
    fmt.Println("月曜日")
case 2:
    fmt.Println("火曜日")
case 3:
    fmt.Println("水曜日")
case 6, 7:
    fmt.Println("週末")
default:
    fmt.Println("その他")
}

条件付きswitch

score := 85

switch {
case score >= 90:
    fmt.Println("A")
case score >= 80:
    fmt.Println("B")
case score >= 70:
    fmt.Println("C")
case score >= 60:
    fmt.Println("D")
default:
    fmt.Println("F")
}

型switch

func describe(i interface{}) {
    switch v := i.(type) {
    case int:
        fmt.Printf("整数: %d\n", v)
    case string:
        fmt.Printf("文字列: %s\n", v)
    case bool:
        fmt.Printf("真偽値: %t\n", v)
    default:
        fmt.Printf("不明な型: %T\n", v)
    }
}

describe(42)       // 整数: 42
describe("hello")  // 文字列: hello
describe(true)     // 真偽値: true

fallthrough

n := 1

switch n {
case 1:
    fmt.Println("1")
    fallthrough  // 次のcaseも実行
case 2:
    fmt.Println("2")
case 3:
    fmt.Println("3")
}
// 出力:
// 1
// 2

ループ

for文(基本)

// 基本のfor文
for i := 0; i < 5; i++ {
    fmt.Println(i)
}

// 逆順
for i := 4; i >= 0; i-- {
    fmt.Println(i)
}

// ステップを変更
for i := 0; i < 10; i += 2 {
    fmt.Println(i)  // 0, 2, 4, 6, 8
}

while相当

// Goにはwhileがない、forで代用
count := 0
for count < 5 {
    fmt.Println(count)
    count++
}

無限ループ

for {
    fmt.Println("無限ループ")
    break  // breakで抜ける
}

range

// スライス
numbers := []int{1, 2, 3, 4, 5}
for index, value := range numbers {
    fmt.Printf("index: %d, value: %d\n", index, value)
}

// インデックスのみ
for i := range numbers {
    fmt.Println(i)
}

// 値のみ
for _, value := range numbers {
    fmt.Println(value)
}

// マップ
scores := map[string]int{"太郎": 85, "花子": 92}
for key, value := range scores {
    fmt.Printf("%s: %d\n", key, value)
}

// 文字列(ルーン)
for i, r := range "こんにちは" {
    fmt.Printf("%d: %c\n", i, r)
}

break と continue

// break
for i := 0; i < 10; i++ {
    if i == 5 {
        break
    }
    fmt.Println(i)  // 0, 1, 2, 3, 4
}

// continue
for i := 0; i < 10; i++ {
    if i%2 == 0 {
        continue
    }
    fmt.Println(i)  // 1, 3, 5, 7, 9
}

ラベル付きbreak/continue

outer:
for i := 0; i < 3; i++ {
    for j := 0; j < 3; j++ {
        if i == 1 && j == 1 {
            break outer  // 外側のループを抜ける
        }
        fmt.Printf("i=%d, j=%d\n", i, j)
    }
}

defer

関数終了時に実行される処理を登録します。

func example() {
    defer fmt.Println("最後に実行")
    fmt.Println("最初に実行")
}
// 出力:
// 最初に実行
// 最後に実行

複数のdefer(LIFO)

func example() {
    defer fmt.Println("1")
    defer fmt.Println("2")
    defer fmt.Println("3")
}
// 出力:
// 3
// 2
// 1

deferでリソース解放

func readFile(path string) error {
    file, err := os.Open(path)
    if err != nil {
        return err
    }
    defer file.Close()  // 関数終了時に必ず閉じる

    // ファイル処理
    return nil
}

panic と recover

func mayPanic() {
    panic("エラーが発生しました")
}

func safeCall() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("回復しました:", r)
        }
    }()

    mayPanic()
    fmt.Println("これは実行されない")
}

func main() {
    safeCall()
    fmt.Println("プログラムは続行します")
}
// 出力:
// 回復しました: エラーが発生しました
// プログラムは続行します

実践例:素数判定

package main

import (
    "fmt"
    "math"
)

func isPrime(n int) bool {
    if n < 2 {
        return false
    }
    for i := 2; i <= int(math.Sqrt(float64(n))); i++ {
        if n%i == 0 {
            return false
        }
    }
    return true
}

func main() {
    for i := 1; i <= 100; i++ {
        if isPrime(i) {
            fmt.Println(i)
        }
    }
}

実践例:FizzBuzz

package main

import "fmt"

func main() {
    for i := 1; i <= 30; i++ {
        switch {
        case i%15 == 0:
            fmt.Println("FizzBuzz")
        case i%3 == 0:
            fmt.Println("Fizz")
        case i%5 == 0:
            fmt.Println("Buzz")
        default:
            fmt.Println(i)
        }
    }
}

まとめ

  • if文は初期化文を含められる
  • switchbreak不要、fallthroughで次へ
  • 型switchで動的な型判定
  • forのみでwhile相当も表現
  • rangeでコレクションをイテレート
  • deferで後処理を登録(LIFO順)
  • panic/recoverで例外的状況に対応

次回は関数について学びます。

広告エリア