コンテンツにスキップ

Go/bool

出典: フリー教科書『ウィキブックス(Wikibooks)』
< Go

Goのboolについて

[編集]

Goにおけるboolは真偽値を表す組み込み型で、trueまたはfalseの2つの値のみを取ります。論理演算やフロー制御に使用される基本的なデータ型です。

基本情報

[編集]
  • bool型はtrueまたはfalseの値のみを持つ
  • メモリ上では1バイト(8ビット)を占める
  • デフォルト値(ゼロ値)はfalse
  • 数値型との自動変換はない(C言語JavaScriptなどと異なる)

他のキーワードとの組み合わせ

[編集]

変数宣言との組み合わせ

[編集]
var isValid bool       // 宣言のみ(falseで初期化される)
var isActive bool = true  // 宣言と初期化
isDone := false       // 短縮変数宣言と初期化

定数定義との組み合わせ

[編集]
const DEBUG bool = true
const (
    ENABLED  bool = true
    DISABLED bool = false
)

関数パラメータと戻り値

[編集]
func isEven(num int) bool {
    return num%2 == 0
}

func processData(data []int, checkZero bool) (bool, error) {
    // 処理ロジック
    return true, nil
}

型変換

[編集]

Goでは数値とbool型の間の直接変換はサポートされていませんが、明示的に変換することはできます:

// 数値からboolへの変換
func intToBool(i int) bool {
    return i != 0
}

// boolから数値への変換
func boolToInt(b bool) int {
    if b {
        return 1
    }
    return 0
}

配列とスライス

[編集]
var flags [5]bool            // bool型の固定長配列
states := make([]bool, 10)   // bool型のスライス
checks := []bool{true, false, true, true} // 初期化付きスライス

マップ

[編集]
featureFlags := make(map[string]bool)
featureFlags["darkMode"] = true
featureFlags["betaFeatures"] = false

userPermissions := map[string]bool{
    "read":   true,
    "write":  true,
    "delete": false,
}

構造体のフィールド

[編集]
type User struct {
    ID       int
    Name     string
    IsActive bool
    IsAdmin  bool
}

type Configuration struct {
    Debug      bool
    Verbose    bool
    LogToFile  bool
    EnableSSL  bool
}

インターフェースと型アサーション

[編集]
func printIfBool(v interface{}) {
    if b, ok := v.(bool); ok {
        fmt.Printf("値は %t です\n", b)
    } else {
        fmt.Println("値はbool型ではありません")
    }
}

論理演算子

[編集]
a, b := true, false

and := a && b  // 論理積(AND): false
or := a || b   // 論理和(OR): true
not := !a      // 否定(NOT): false

// ショートサーキット評価
if isEnabled && performCheck() {
    // isEnabledがfalseの場合、performCheck()は実行されない
}

if isDisabled || fallbackEnabled() {
    // isDisabledがtrueの場合、fallbackEnabled()は実行されない
}

一般的なユースケース

[編集]
  1. 条件分岐(if文)
       isValid := checkInput(input)
       
       if isValid {
           fmt.Println("入力は有効です")
       } else {
           fmt.Println("入力が無効です")
       }
       
       // 条件式の結果をbool変数に格納
       isEmpty := len(data) == 0
       if isEmpty {
           // 処理
       }
    
  2. for文での反復制御
       isRunning := true
       count := 0
       
       for isRunning {
           count++
           if count >= 10 {
               isRunning = false
           }
       }
    
  3. フラグとオプション設定
       type Options struct {
           EnableLogging bool
           VerboseOutput bool
           StrictMode    bool
       }
       
       func processWithOptions(data []byte, opt Options) []byte {
           if opt.EnableLogging {
               log.Println("処理開始")
           }
           
           result := process(data)
           
           if opt.StrictMode && hasErrors(result) {
               panic("厳格モードでエラーが発生しました")
           }
           
           return result
       }
    
  4. ステータス管理と状態追跡
       type TaskStatus struct {
           IsStarted    bool
           IsProcessing bool
           IsDone       bool
           HasErrors    bool
       }
       
       func (t *TaskStatus) markStarted() {
           t.IsStarted = true
           t.IsProcessing = true
           t.IsDone = false
           t.HasErrors = false
       }
       
       func (t *TaskStatus) markDone() {
           t.IsProcessing = false
           t.IsDone = true
       }
    
  5. バリデーション結果の返却
       func validateEmail(email string) bool {
           // 電子メールの検証ロジック
           return regexp.MustCompile(`.+@.+\..+`).MatchString(email)
       }
       
       func validateUser(user User) map[string]bool {
           validations := make(map[string]bool)
           
           validations["name"] = len(user.Name) > 0
           validations["email"] = validateEmail(user.Email)
           validations["age"] = user.Age > 0
           
           return validations
       }
    
  6. セット実装(存在確認)
       type StringSet map[string]bool
       
       func NewStringSet() StringSet {
           return make(StringSet)
       }
       
       func (s StringSet) Add(item string) {
           s[item] = true
       }
       
       func (s StringSet) Remove(item string) {
           delete(s, item)
       }
       
       func (s StringSet) Contains(item string) bool {
           _, exists := s[item]
           return exists
       }
    
  7. メモ化(計算結果のキャッシュ)
       type Memoizer struct {
           cache map[string]interface{}
           done  map[string]bool
       }
       
       func NewMemoizer() *Memoizer {
           return &Memoizer{
               cache: make(map[string]interface{}),
               done:  make(map[string]bool),
           }
       }
       
       func (m *Memoizer) Compute(key string, fn func() interface{}) interface{} {
           if m.done[key] {
               return m.cache[key]
           }
           
           result := fn()
           m.cache[key] = result
           m.done[key] = true
           return result
       }
    
  8. ビジネスルールの実装
       func canUserAccessResource(user User, resource Resource) bool {
           if user.IsAdmin {
               return true
           }
           
           if resource.IsPublic {
               return true
           }
           
           return resource.OwnerID == user.ID
       }
       
       func shouldSendNotification(user User, event Event) bool {
           if !user.NotificationsEnabled {
               return false
           }
           
           if event.Severity < user.MinNotificationSeverity {
               return false
           }
           
           return true
       }
    
  9. 並行処理における同期と通知
       func worker(jobs <-chan Job, done chan<- bool) {
           for job := range jobs {
               processJob(job)
           }
           done <- true // 処理完了を通知
       }
       
       func main() {
           jobs := make(chan Job, 100)
           done := make(chan bool)
           
           // ワーカーを起動
           for i := 0; i < 5; i++ {
               go worker(jobs, done)
           }
           
           // ジョブを送信
           for i := 0; i < 100; i++ {
               jobs <- Job{ID: i}
           }
           close(jobs)
           
           // すべてのワーカーが完了するのを待つ
           for i := 0; i < 5; i++ {
               <-done
           }
       }
    
  10. フラグパッケージとの連携
        import "flag"
        
        func main() {
            debugPtr := flag.Bool("debug", false, "デバッグモードを有効にする")
            verbosePtr := flag.Bool("verbose", false, "詳細な出力を有効にする")
            flag.Parse()
            
            if *debugPtr {
                fmt.Println("デバッグモードが有効です")
            }
            
            if *verbosePtr {
                fmt.Println("詳細出力モードが有効です")
            }
        }
        // 実行: ./program -debug -verbose
    
  11. テスト結果の検証
        import "testing"
        
        func TestAddition(t *testing.T) {
            result := Add(2, 3)
            expected := 5
            
            if result != expected {
                t.Errorf("Add(2, 3)の結果が%dになるはずが、%dになりました", expected, result)
            }
            
            // 検証用ヘルパー関数の使用
            if !reflect.DeepEqual(actualList, expectedList) {
                t.Errorf("リストが一致しません")
            }
        }
    

特別なユースケースと注意点

[編集]
  1. JSONやDBとの相互変換
       type Feature struct {
           Name    string `json:"name"`
           Enabled bool   `json:"enabled"`
       }
       
       // JSONからの変換
       jsonStr := `{"name": "darkMode", "enabled": true}`
       var feature Feature
       json.Unmarshal([]byte(jsonStr), &feature)
       
       // JSONへの変換
       featureJSON, _ := json.Marshal(feature)
    
  2. bool型のポインタ使用(nilになりうる)
       type Settings struct {
           Debug *bool // nilまたはtrue/falseを持つことができる
       }
       
       func getDefaultSettings() Settings {
           debug := true
           return Settings{
               Debug: &debug,
           }
       }
       
       func updateSettings(s Settings, debug *bool) {
           if debug != nil {
               s.Debug = debug
           }
       }
    
  3. boolと数値型の関係
       // Goでは以下のコードはコンパイルエラーになる
       // var i int = 1
       // var b bool = i  // エラー
       // var j int = b   // エラー
       
       // 明示的な変換が必要
       var i int = 1
       var b bool = i != 0  // OK
       var j int
       if b {
           j = 1
       } else {
           j = 0
       }
    
  4. bool値の文字列表現
       trueStr := fmt.Sprintf("%t", true)   // "true"
       falseStr := strconv.FormatBool(false) // "false"
       
       parsedBool, err := strconv.ParseBool("true")  // true, nil
       anotherBool, err := strconv.ParseBool("1")    // true, nil (1, t, T, TRUE, trueも可)
    
  5. unsafe.Sizeofでのサイズ確認
       import "unsafe"
       
       func main() {
           var b bool
           fmt.Println(unsafe.Sizeof(b)) // 1バイト
       }
    
  6. 三項演算子の代替
       // Goには三項演算子がないため、if-elseを使用
       value := 10
       var result string
       if value > 5 {
           result = "大きい"
       } else {
           result = "小さい"
       }
       
       // または関数を使用
       func ternary(condition bool, trueVal, falseVal string) string {
           if condition {
               return trueVal
           }
           return falseVal
       }
       result = ternary(value > 5, "大きい", "小さい")
    

bool型は単純ながらも、条件分岐や状態管理など多くの場面で重要な役割を果たします。Goでは他の言語と異なり、数値とbool型の自動変換を行わないため、型の安全性が高くなっています。