Go言語入門:言語仕様 -Vol.19-

スポンサーリンク
Go言語入門:言語仕様 -Vol.19- 用語解説
Go言語入門:言語仕様 -Vol.19-
この記事は約17分で読めます。
よっしー
よっしー

こんにちは。よっしーです(^^)

本日は、Go言語の言語仕様について解説しています。

スポンサーリンク

背景

Go言語を学び始めて、公式の「The Go Programming Language Specification(言語仕様書)」を開いてみたものの、「英語で書かれていて読むのが大変…」「専門用語ばかりで何を言っているのかわからない…」と感じたことはありませんか? 実は、多くのGo初心者が同じ壁にぶつかっています。

言語仕様書は、Go言語の「正式な取扱説明書」のような存在です。プログラミング言語がどのように動くのか、どんなルールで書くべきなのかが詳しく書かれていますが、その分、初めて読む人には難しく感じられるのも事実です。

そこでこの記事では、言語仕様書の導入部分を丁寧な日本語訳とともに、初心者の方でも理解しやすい補足説明を加えてお届けします。「強く型付けされている」「ガベージコレクション」「並行プログラミング」といった専門用語も、具体例を交えながらわかりやすく解説していきます。

言語仕様書は難しそうに見えますが、一つひとつの概念を丁寧に読み解いていけば、必ず理解できます。一緒に、Go言語の基礎をしっかり学んでいきましょう!

Boolean types(真偽値型)

真偽値型は、事前宣言された定数truefalseで示されるブール真理値の集合を表します。事前宣言された真偽値型はboolです。これは定義された型です。


解説

真偽値型とは何か?

真偽値型(boolean type) は、「正しい(真)」か「間違っている(偽)」の2つの値だけを持つ型です。Goではbool型として提供されています。

たとえ話: 電気のスイッチのように、「ON」か「OFF」の2つの状態しかないものを表現します。質問に対する「はい/いいえ」の答えや、条件が満たされているかどうかを表すのに使います。

package main

import "fmt"

func main() {
    // 真偽値型の変数
    var isStudent bool = true
    var hasLicense bool = false
    
    fmt.Println("学生ですか?", isStudent)    // true
    fmt.Println("免許を持っていますか?", hasLicense)  // false
}

1. bool型の基本

使える値は2つだけ

package main

import "fmt"

func main() {
    // trueとfalseだけ
    var t bool = true
    var f bool = false
    
    fmt.Println(t)  // true
    fmt.Println(f)  // false
    
    // これはエラー
    // var invalid bool = 1  // エラー!
    // var invalid2 bool = "true"  // エラー!
}

ゼロ値はfalse

宣言だけして値を設定しない場合、**自動的にfalse**になります。

package main

import "fmt"

func main() {
    var b bool  // 初期化していない
    fmt.Println(b)  // false (ゼロ値)
    
    // 明示的にfalseを設定するのと同じ
    var b2 bool = false
    fmt.Println(b == b2)  // true
}

2. 比較演算子との組み合わせ

真偽値は、比較演算子の結果として得られることが多いです。

等価比較

package main

import "fmt"

func main() {
    age := 20
    
    // == (等しい)
    isAdult := age == 20
    fmt.Println("20歳ですか?", isAdult)  // true
    
    // != (等しくない)
    isNotTeen := age != 19
    fmt.Println("19歳ではないですか?", isNotTeen)  // true
}

大小比較

package main

import "fmt"

func main() {
    score := 85
    
    // > (より大きい)
    isHigh := score > 80
    fmt.Println("80点より高いですか?", isHigh)  // true
    
    // >= (以上)
    isPassing := score >= 60
    fmt.Println("合格点以上ですか?", isPassing)  // true
    
    // < (より小さい)
    isLow := score < 50
    fmt.Println("50点未満ですか?", isLow)  // false
    
    // <= (以下)
    isNotPerfect := score <= 100
    fmt.Println("100点以下ですか?", isNotPerfect)  // true
}

3. 論理演算子

複数の真偽値を組み合わせるには、論理演算子を使います。

&& (論理積・AND)

**両方ともtrue**の場合だけtrueになります。

package main

import "fmt"

func main() {
    age := 25
    hasLicense := true
    
    // 両方の条件を満たす?
    canDrive := age >= 18 && hasLicense
    fmt.Println("運転できますか?", canDrive)  // true
    
    // 真理値表
    fmt.Println(true && true)    // true
    fmt.Println(true && false)   // false
    fmt.Println(false && true)   // false
    fmt.Println(false && false)  // false
}

|| (論理和・OR)

**どちらか一方でもtrue**ならtrueになります。

package main

import "fmt"

func main() {
    day := "土曜日"
    
    // どちらかの条件を満たす?
    isWeekend := day == "土曜日" || day == "日曜日"
    fmt.Println("週末ですか?", isWeekend)  // true
    
    // 真理値表
    fmt.Println(true || true)    // true
    fmt.Println(true || false)   // true
    fmt.Println(false || true)   // true
    fmt.Println(false || false)  // false
}

! (論理否定・NOT)

真偽値を反転します。

package main

import "fmt"

func main() {
    isRaining := false
    
    // 否定
    isSunny := !isRaining
    fmt.Println("晴れですか?", isSunny)  // true
    
    // 真理値表
    fmt.Println(!true)   // false
    fmt.Println(!false)  // true
    
    // 二重否定
    fmt.Println(!!true)  // true
}

4. 条件分岐での使用

真偽値は、if文やfor文でよく使われます。

if文

package main

import "fmt"

func main() {
    age := 20
    hasTicket := true
    
    // 単一の条件
    if age >= 18 {
        fmt.Println("成人です")
    }
    
    // 複数の条件(AND)
    if age >= 18 && hasTicket {
        fmt.Println("イベントに参加できます")
    }
    
    // 複数の条件(OR)
    day := "土曜日"
    if day == "土曜日" || day == "日曜日" {
        fmt.Println("週末です")
    }
    
    // 否定
    isWorking := false
    if !isWorking {
        fmt.Println("休みです")
    }
}

for文

package main

import "fmt"

func main() {
    // 条件がtrueの間ループ
    count := 0
    for count < 5 {
        fmt.Println(count)
        count++
    }
    
    // 無限ループ(常にtrue)
    // for true {
    //     fmt.Println("無限ループ")
    //     break  // breakで抜ける
    // }
    
    // 単にforと書いても同じ
    // for {
    //     fmt.Println("無限ループ")
    //     break
    // }
}

5. 関数の戻り値として

真偽値を返す関数は、判定関数としてよく使われます。慣習として、関数名をIs...Has...で始めることが多いです。

package main

import "fmt"

// 成人かどうか判定
func IsAdult(age int) bool {
    return age >= 18
}

// 偶数かどうか判定
func IsEven(n int) bool {
    return n%2 == 0
}

// 空文字列かどうか判定
func IsEmpty(s string) bool {
    return s == ""
}

func main() {
    fmt.Println(IsAdult(20))     // true
    fmt.Println(IsAdult(15))     // false
    
    fmt.Println(IsEven(4))       // true
    fmt.Println(IsEven(7))       // false
    
    fmt.Println(IsEmpty(""))     // true
    fmt.Println(IsEmpty("Hello")) // false
}

6. 短絡評価(Short-circuit evaluation)

&&||短絡評価を行います。つまり、結果が確定した時点で評価を停止します。

&&の短絡評価

左側がfalseなら、右側は評価されません。

package main

import "fmt"

func main() {
    x := 0
    
    // x != 0 が false なので、10/x は評価されない(ゼロ除算を回避)
    if x != 0 && 10/x > 2 {
        fmt.Println("OK")
    } else {
        fmt.Println("xがゼロまたは条件不一致")
    }
}

||の短絡評価

左側がtrueなら、右側は評価されません。

package main

import "fmt"

func expensiveCheck() bool {
    fmt.Println("高コストな処理を実行")
    return true
}

func main() {
    quickCheck := true
    
    // quickCheck が true なので、expensiveCheck() は呼ばれない
    if quickCheck || expensiveCheck() {
        fmt.Println("OK")
    }
    // 出力: OK のみ(「高コストな処理を実行」は出力されない)
}

7. 実用例

例1: ユーザー認証チェック

package main

import "fmt"

type User struct {
    Name     string
    Password string
    IsActive bool
}

func Authenticate(user User, password string) bool {
    // すべての条件を満たす必要がある
    return user.IsActive && user.Password == password
}

func main() {
    user := User{
        Name:     "太郎",
        Password: "secret123",
        IsActive: true,
    }
    
    if Authenticate(user, "secret123") {
        fmt.Println("認証成功")
    } else {
        fmt.Println("認証失敗")
    }
}

例2: 範囲チェック

package main

import "fmt"

func IsInRange(value, min, max int) bool {
    return value >= min && value <= max
}

func main() {
    score := 75
    
    if IsInRange(score, 0, 100) {
        fmt.Println("有効なスコアです")
    }
    
    if IsInRange(score, 60, 100) {
        fmt.Println("合格です")
    }
}

例3: バリデーション

package main

import (
    "fmt"
    "strings"
)

type UserInput struct {
    Name  string
    Email string
    Age   int
}

func Validate(input UserInput) (bool, string) {
    // 名前チェック
    if input.Name == "" {
        return false, "名前が空です"
    }
    
    // メールチェック
    if !strings.Contains(input.Email, "@") {
        return false, "メールアドレスが無効です"
    }
    
    // 年齢チェック
    if input.Age < 0 || input.Age > 150 {
        return false, "年齢が無効です"
    }
    
    return true, "OK"
}

func main() {
    user := UserInput{
        Name:  "太郎",
        Email: "taro@example.com",
        Age:   25,
    }
    
    if valid, message := Validate(user); valid {
        fmt.Println("バリデーション成功")
    } else {
        fmt.Println("エラー:", message)
    }
}

例4: フラグの組み合わせ

package main

import "fmt"

func main() {
    hasPermissionRead := true
    hasPermissionWrite := false
    hasPermissionDelete := false
    
    // 読み取り専用
    isReadOnly := hasPermissionRead && !hasPermissionWrite && !hasPermissionDelete
    fmt.Println("読み取り専用:", isReadOnly)  // true
    
    // フルアクセス
    isFullAccess := hasPermissionRead && hasPermissionWrite && hasPermissionDelete
    fmt.Println("フルアクセス:", isFullAccess)  // false
    
    // 何らかの権限あり
    hasAnyPermission := hasPermissionRead || hasPermissionWrite || hasPermissionDelete
    fmt.Println("何らかの権限:", hasAnyPermission)  // true
}

例5: 状態管理

package main

import "fmt"

type Application struct {
    IsRunning    bool
    IsConnected  bool
    HasError     bool
}

func (app *Application) CanProcessData() bool {
    return app.IsRunning && app.IsConnected && !app.HasError
}

func main() {
    app := Application{
        IsRunning:   true,
        IsConnected: true,
        HasError:    false,
    }
    
    if app.CanProcessData() {
        fmt.Println("データ処理可能")
    } else {
        fmt.Println("データ処理不可")
    }
    
    // エラー発生
    app.HasError = true
    
    if app.CanProcessData() {
        fmt.Println("データ処理可能")
    } else {
        fmt.Println("データ処理不可")  // こちらが出力される
    }
}

8. よくある間違い

間違い1: 数値との混同

package main

func main() {
    // ❌ 間違い: 他の言語(C言語など)と違い、数値と真偽値は別物
    // var b bool = 1  // コンパイルエラー!
    // var b2 bool = 0  // コンパイルエラー!
    
    // ✅ 正しい
    var b bool = true
    var b2 bool = false
    
    _ = b
    _ = b2
}

間違い2: 冗長な比較

package main

import "fmt"

func main() {
    isStudent := true
    
    // ❌ 冗長(悪い例)
    if isStudent == true {
        fmt.Println("学生です")
    }
    
    // ✅ シンプル(良い例)
    if isStudent {
        fmt.Println("学生です")
    }
    
    // ❌ 冗長(悪い例)
    if isStudent == false {
        fmt.Println("学生ではありません")
    }
    
    // ✅ シンプル(良い例)
    if !isStudent {
        fmt.Println("学生ではありません")
    }
}

間違い3: 不要な三項演算子風のコード

package main

func main() {
    age := 20
    
    // ❌ 冗長(悪い例)
    var isAdult bool
    if age >= 18 {
        isAdult = true
    } else {
        isAdult = false
    }
    
    // ✅ シンプル(良い例)
    isAdult := age >= 18
    
    _ = isAdult
}

まとめ: 真偽値型で覚えておくべきこと

基本事項

  1. 型名: bool
  2. 使える値: truefalseだけ
  3. ゼロ値: false
  4. 定義された型: 独自の型として定義されている

論理演算子

演算子意味結果
&&AND(論理積)true && falsefalse
``OR(論理和)
!NOT(否定)!truefalse

比較演算子

演算子意味結果
==等しい5 == 5true
!=等しくない5 != 3true
<より小さい3 < 5true
<=以下5 <= 5true
>より大きい5 > 3true
>=以上5 >= 5true

実用的なアドバイス

package main

import "fmt"

func main() {
    // 1. シンプルに書く
    isValid := true
    if isValid {  // isValid == true は冗長
        fmt.Println("有効")
    }
    
    // 2. 意味のある変数名を使う
    isStudent := true      // OK
    flag := true           // 意味不明(避ける)
    
    // 3. 判定関数は Is/Has で始める
    age := 20
    isAdult := age >= 18
    
    // 4. 複雑な条件は関数に切り出す
    if isEligibleForDiscount(age, isStudent) {
        fmt.Println("割引適用")
    }
}

func isEligibleForDiscount(age int, isStudent bool) bool {
    return age < 18 || age >= 65 || isStudent
}

真偽値型は、プログラムの制御フローを決める重要な型です。条件分岐やループ、判定処理など、あらゆる場面で使われます!

おわりに 

本日は、Go言語の言語仕様について解説しました。

よっしー
よっしー

何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。

それでは、また明日お会いしましょう(^^)

コメント

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