【初心者向け】Go言語のif文を完全マスター!基本構文から実践テクニックまで解説

Go

Go(Golang)を学び始めたばかりの人にとって、「if文」は最初の関門の一つです。

他の言語と似ているようで微妙に違うGoのif文は、書き方にクセがあり、知らずにエラーを出してしまうこともあります。

特に、C言語やJavaから来た人は「なぜカッコがエラーになるの?」「なぜelseが改行できないの?」と戸惑うことが多いです。

この記事では、Go言語におけるif文の基本から、初学者がつまずきやすいポイント、実用的な書き方のコツまで、わかりやすくまとめました。

「ifの中で変数定義できるの?」「else ifは使える?」「スコープって何?」といった疑問にも、具体例つきでお答えします!

スポンサーリンク

Go言語におけるif文の基本構文

基本形(最もシンプルな例)

if 条件式 {
    // 条件がtrueのときの処理
}

Goの特徴:

  • 条件式のカッコ () は不要(エラーになる)
  • 波カッコ {} は必須(省略不可)

具体例で理解しよう

package main

import "fmt"

func main() {
    x := 10
    
    if x > 5 {
        fmt.Println("xは5より大きい")
    }
    
    // 出力:xは5より大きい
}

他の言語との比較

言語書き方Goでの対応
C/Javaif (x > 5) { ... }❌ カッコは不要
Pythonif x > 5:❌ 波カッコが必須
Goif x > 5 { ... }✅ 正しい

else と else if の使い方

func checkNumber(x int) {
    if x > 0 {
        fmt.Println("正の数です")
    } else if x < 0 {
        fmt.Println("負の数です")
    } else {
        fmt.Println("ゼロです")
    }
}

実行例:

checkNumber(5)   // 出力:正の数です
checkNumber(-3)  // 出力:負の数です
checkNumber(0)   // 出力:ゼロです

複雑な条件式

func checkAge(age int) {
    if age >= 18 && age < 65 {
        fmt.Println("働ける年齢です")
    } else if age >= 65 {
        fmt.Println("シニア世代です")
    } else {
        fmt.Println("未成年です")
    }
}

論理演算子:

  • &&:AND(両方がtrue)
  • ||:OR(どちらかがtrue)
  • !:NOT(否定)

ポイント: Goのif文は、カッコを使わず、波カッコは必須。基本はシンプルです。

Go独特の機能:if文の中で変数を定義する

変数初期化付きif文

Go言語では、if文の中で変数の初期化と評価を同時に行うことができます。

基本構文:

if 変数 := 式; 条件 {
    // 処理
}

具体例:

package main

import (
    "fmt"
    "math/rand"
)

func getRandomNumber() int {
    return rand.Intn(100)
}

func main() {
    if num := getRandomNumber(); num > 50 {
        fmt.Printf("生成された数値 %d は50より大きい\n", num)
    } else {
        fmt.Printf("生成された数値 %d は50以下\n", num)
    }
}

スコープ(変数の有効範囲)

重要なポイント:

  • numのスコープはif文全体(else、else ifを含む)
  • if文の外ではnumは使えない
func example() {
    if num := 10; num > 5 {
        fmt.Println(num) // ✅ 使える
    } else {
        fmt.Println(num) // ✅ 使える(elseでも有効)
    }
    
    // fmt.Println(num) // ❌ エラー!if文の外では使えない
}

実用的な使用例

ファイル処理の例:

func readFile(filename string) {
    if file, err := os.Open(filename); err != nil {
        fmt.Printf("ファイルが開けません: %v\n", err)
    } else {
        defer file.Close()
        fmt.Println("ファイルを正常に開きました")
        // ここでfileを使った処理
    }
}

文字列処理の例:

func checkString() {
    text := "Hello, World!"
    
    if length := len(text); length > 10 {
        fmt.Printf("文字列は長い(%d文字)\n", length)
    } else {
        fmt.Printf("文字列は短い(%d文字)\n", length)
    }
}

使いどころ

場面
関数の戻り値をすぐ評価if result := calc(); result > 0
エラーハンドリングif err := doSomething(); err != nil
一時的な計算結果if sum := a + b; sum > 100

ポイント: Goでは、if文の条件の中で変数を定義できるという便利な特徴があります。

初心者がよくやるif文のミスとその対策

よくある間違い① 条件式にカッコをつけてしまう

❌ 間違った書き方(C/Java風):

if (x > 0) {
    fmt.Println("正の数")
}

エラーメッセージ:

syntax error: unexpected (, expecting {

✅ 正しい書き方:

if x > 0 {
    fmt.Println("正の数")
}

よくある間違い② 波カッコを省略する

❌ 間違った書き方:

if x > 0 
    fmt.Println("正の数")  // エラー!

// または
if x > 0 fmt.Println("正の数")  // エラー!

✅ 正しい書き方:

if x > 0 {
    fmt.Println("正の数")
}

重要: Goでは波カッコは必須。1行でも省略できません。

よくある間違い③ elseの前に改行してしまう

❌ 間違った書き方:

if x > 0 {
    fmt.Println("正")
}
else {  // エラー!
    fmt.Println("負")
}

エラーメッセージ:

syntax error: unexpected else, expecting }

✅ 正しい書き方:

if x > 0 {
    fmt.Println("正")
} else {  // 同じ行に書く
    fmt.Println("負")
}

よくある間違い④ 変数のスコープを間違える

❌ 間違った使い方:

if num := 10; num > 5 {
    fmt.Println("条件内:", num)
}
fmt.Println("条件外:", num)  // エラー!numは存在しない

✅ 正しい使い方:

// パターン1:事前に変数を定義
num := 10
if num > 5 {
    fmt.Println("条件内:", num)
}
fmt.Println("条件外:", num)  // OK

// パターン2:if文内でのみ使用
if num := 10; num > 5 {
    fmt.Println("条件内:", num)
    // この中でのみnumを使用
}

間違いを避けるコツ

注意点覚え方
カッコ不要「Goはシンプル、カッコいらず」
波カッコ必須「1行でも波カッコは友達」
elseは同じ行「elseは恥ずかしがり屋、離れたくない」
スコープに注意「if文の中で生まれた変数は、if文の中で生涯を終える」

ポイント: Goのif文は見た目は簡単でも、細かい構文ミスが多発します。この決まりを覚えて慣れましょう。

実践!Goのif文活用テクニック

エラーハンドリングパターン

Goではエラー処理にif文を多用します。これはGoらしいコードスタイルです。

基本的なエラーハンドリング:

func divide(a, b int) (int, error) {
    if b == 0 {
        return 0, fmt.Errorf("ゼロで割ることはできません")
    }
    return a / b, nil
}

func main() {
    if result, err := divide(10, 2); err != nil {
        fmt.Printf("エラー: %v\n", err)
    } else {
        fmt.Printf("結果: %d\n", result)
    }
}

ファイル操作でのエラーハンドリング:

func readConfigFile() {
    if data, err := os.ReadFile("config.txt"); err != nil {
        log.Printf("設定ファイルが読めません: %v", err)
        // デフォルト設定を使用
        useDefaultConfig()
    } else {
        fmt.Printf("設定を読み込みました: %s\n", string(data))
    }
}

文字列処理での活用

func processString(text string) {
    // 文字列が空かチェック
    if len(text) == 0 {
        fmt.Println("空の文字列です")
        return
    }
    
    // 特定の文字列を含むかチェック
    if strings.Contains(text, "Go") {
        fmt.Println("Go言語に関する内容です")
    }
    
    // 文字列の長さで処理を分岐
    if length := len(text); length > 100 {
        fmt.Printf("長い文章です(%d文字)\n", length)
    } else {
        fmt.Printf("短い文章です(%d文字)\n", length)
    }
}

数値計算での活用

func calculateGrade(score int) string {
    if score < 0 || score > 100 {
        return "無効なスコアです"
    }
    
    if score >= 90 {
        return "A"
    } else if score >= 80 {
        return "B"
    } else if score >= 70 {
        return "C"
    } else if score >= 60 {
        return "D"
    } else {
        return "F"
    }
}

スライス・マップでの活用

func processSlice(numbers []int) {
    // スライスが空かチェック
    if len(numbers) == 0 {
        fmt.Println("データがありません")
        return
    }
    
    // 最初の要素をチェック
    if first := numbers[0]; first > 0 {
        fmt.Printf("最初の要素は正の数: %d\n", first)
    }
}

func processMap(data map[string]int) {
    // キーが存在するかチェック
    if value, exists := data["score"]; exists {
        fmt.Printf("スコア: %d\n", value)
    } else {
        fmt.Println("スコアが設定されていません")
    }
}

HTTP処理での活用

func handleRequest(w http.ResponseWriter, r *http.Request) {
    // HTTPメソッドをチェック
    if r.Method != http.MethodPost {
        http.Error(w, "POSTメソッドのみ対応", http.StatusMethodNotAllowed)
        return
    }
    
    // リクエストボディをパース
    if err := r.ParseForm(); err != nil {
        http.Error(w, "フォームの解析に失敗", http.StatusBadRequest)
        return
    }
    
    // パラメータの存在チェック
    if name := r.FormValue("name"); name == "" {
        http.Error(w, "nameパラメータが必要", http.StatusBadRequest)
        return
    } else {
        fmt.Fprintf(w, "こんにちは、%sさん!", name)
    }
}

設定値の検証

type Config struct {
    Port     int
    Host     string
    Database string
}

func validateConfig(config Config) error {
    if config.Port <= 0 || config.Port > 65535 {
        return fmt.Errorf("無効なポート番号: %d", config.Port)
    }
    
    if config.Host == "" {
        return fmt.Errorf("ホスト名が設定されていません")
    }
    
    if config.Database == "" {
        return fmt.Errorf("データベース名が設定されていません")
    }
    
    return nil
}

ポイント: Goのif文は、戻り値の評価やエラー処理にとても役立ちます。

Goのif文のベストプラクティス

早期return(Early Return)を活用

❌ ネストが深い書き方:

func processUser(user User) error {
    if user.Name != "" {
        if user.Age >= 0 {
            if user.Email != "" {
                // 実際の処理
                return saveUser(user)
            } else {
                return fmt.Errorf("メールアドレスが必要")
            }
        } else {
            return fmt.Errorf("年齢は0以上である必要があります")
        }
    } else {
        return fmt.Errorf("名前が必要")
    }
}

✅ 早期returnでスッキリ:

func processUser(user User) error {
    if user.Name == "" {
        return fmt.Errorf("名前が必要")
    }
    
    if user.Age < 0 {
        return fmt.Errorf("年齢は0以上である必要があります")
    }
    
    if user.Email == "" {
        return fmt.Errorf("メールアドレスが必要")
    }
    
    // 実際の処理
    return saveUser(user)
}

条件式を変数に分ける

❌ 複雑な条件式:

if user.Age >= 18 && user.HasLicense && user.ExperienceYears >= 2 && !user.HasViolations {
    allowDriving(user)
}

✅ 意味のある変数名で分割:

isAdult := user.Age >= 18
hasValidLicense := user.HasLicense
hasEnoughExperience := user.ExperienceYears >= 2
hasCleanRecord := !user.HasViolations

if isAdult && hasValidLicense && hasEnoughExperience && hasCleanRecord {
    allowDriving(user)
}

ゼロ値チェックの活用

// 文字列のゼロ値チェック
if name == "" {
    // 空文字列の処理
}

// スライスのゼロ値チェック
if len(items) == 0 {
    // 空スライスの処理
}

// ポインタのゼロ値チェック
if ptr == nil {
    // nilポインタの処理
}

よくある質問と回答

Q: なぜGoはカッコが不要なのですか?

A: Goの設計思想「シンプルさ」のためです

Goは「読みやすく、書きやすく、理解しやすい」言語を目指しています。不要なカッコを省略することで、コードがすっきりし、可読性が向上します。

Q: 三項演算子(? :)は使えますか?

A: Goには三項演算子はありません

// ❌ 三項演算子(Goにはない)
result := x > 0 ? "positive" : "negative"

// ✅ if文を使う
var result string
if x > 0 {
    result = "positive"
} else {
    result = "negative"
}

Q: if文の中でbreak、continueは使えますか?

A: ループの中でのみ使用可能です

for i := 0; i < 10; i++ {
    if i == 5 {
        break    // ✅ ループを抜ける
    }
    if i%2 == 0 {
        continue // ✅ 次のループへ
    }
    fmt.Println(i)
}

Q: if文での型変換はどうしますか?

A: 型アサーションを使用します

func processInterface(v interface{}) {
    if str, ok := v.(string); ok {
        fmt.Printf("文字列: %s\n", str)
    } else if num, ok := v.(int); ok {
        fmt.Printf("整数: %d\n", num)
    } else {
        fmt.Println("未知の型")
    }
}

まとめ:Goのif文を使いこなして、きれいなコードを書こう

今回学んだ重要なポイント:

  • 構文の特徴:カッコ不要、波カッコ必須、elseは同じ行
  • 変数初期化:if文の中で変数を定義できる便利機能
  • スコープ:if文内で定義した変数は、if文内でのみ有効
  • エラーハンドリング:Goらしいコーディングスタイル
  • ベストプラクティス:早期return、条件式の分割

実際に使ってみよう:

  1. 基本的なif文から始めて構文に慣れる
  2. 変数初期化付きif文で短いコードを書いてみる
  3. エラーハンドリングパターンを実践してみる
  4. 早期returnでネストを減らしてみる

コメント

タイトルとURLをコピーしました