Der Datentyp bool in Go dient zur Darstellung von Wahrheitswerten und ist essenziell für logische Operationen und Kontrollstrukturen. Er kann nur die Werte true oder false annehmen und wird häufig in Bedingungen, Vergleichen und Schleifen eingesetzt. In diesem Artikel werden die Eigenschaften, die Verwendung und typische Anwendungsfälle des bool-Typs in Go anhand von Beispielen erläutert.

Einführung

Der bool Datentyp repräsentiert Wahrheitswerte und kann nur zwei mögliche Zustände annehmen: true (wahr) oder false (unwahr). Dieser binäre Charakter macht den bool Typ zu einem unverzichtbaren Werkzeug für Entscheidungslogik, Kontrollfluss und logische Operationen.

In Go ist der bool Typ ein eigenständiger Typ, der sich von Ganzzahlen oder anderen Datentypen unterscheidet und nicht implizit konvertiert werden kann.

Grundlagen und Deklaration

Einfache Deklaration

Die Deklaration einer Boolean-Variable in Go folgt der üblichen Syntax für Variablendeklarationen. Es gibt mehrere Möglichkeiten, eine bool Variable zu deklarieren.

Go Beispiel
package main

import "fmt"

func main() {
    // Explizite Deklaration ohne Initialisierung
    var isValid bool
    fmt.Println("isValid:", isValid)

    // Explizite Deklaration mit Initialisierung
    var isReady bool = true
    fmt.Println("isReady:", isReady)

    // Kurze Deklaration mit Typ-Inferenz
    isComplete := false
    fmt.Println("isComplete:", isComplete)

    // Mehrere Variablen gleichzeitig
    var isActive, isEnabled bool = true, false
    fmt.Println("isActive:", isActive, "isEnabled:", isEnabled)
}
Output
isValid: false
isReady: true
isComplete: false
isActive: true isEnabled: false

Zero-Value

Ein besonders wichtiges Konzept in Go ist der “Zero Value” - der Standardwert, den eine Variable erhält, wenn sie deklariert aber nicht explizit initialisiert wird. Für den bool Typ ist der Zero Value false.

Go Beispiel
package main

import "fmt"

func main() {
    var defaultBool bool
    fmt.Printf("Zero Value von bool: %t\n", defaultBool)

    // Auch in Arrays und Slices
    var boolArray [3]bool
    fmt.Printf("Array mit Zero Values: %t\n", boolArray)

    // In Structs
    type Settings struct {
        DebugMode bool
        Verbose bool
    }

    var config Settings
    fmt.Printf("Struct Zero Values: %t\n", config)
}
Output
Zero Value von bool: false
Array mit Zero Values: [false false false]
Struct Zero Values: {false false}

Werte true und false

Grundlegende Verwendung

Die beiden möglichen Werte des bool Typs sind true und false. Diese sind reservierte Schlüsselwörter in Go und repräsentieren die logischen Konzepte von “wahr” und “falsch”. Sie können nicht als Variablennamen verwendet werden und sind case-sensitive.

Go Beispiel
package main

import "fmt"

func main() {
    // Direkte Zuweisung der Literale
    truthy := true
    falsy := false

    fmt.Printf("Wahr: %t, Falsch: %t\n", truthy, falsy)

    // Boolean-Werte in Berechnungen
    result := truthy && falsy
    fmt.Printf("true AND false = %t\n", result)

    result = truthy || falsy
    fmt.Printf("true OR false = %t\n", result)

    // Negation
    notTruthy := !truthy
    fmt.Printf("NOT true = %t\n", notTruthy)
}
Output
Wahr: true, Falsch: false
true AND false = false
true OR false = true
NOT true = false

Semantische Bedeutung

Boolean-Werte haben in verschiedenen Kontexten unterschiedliche semantische Bedeutungen. Es ist wichtig, aussagekräftige Variablennamen zu wählen, die den Zweck und die Bedeutung der Boolean-Variable klar kommunizieren.

Go Beispiel
package main

import "fmt"

func processData() bool {
    return true
}

func main() {
    // Zustandsangaben
    isLoggedIn := true
    hasPermission := false
    isDataLoaded := true

    // Konfigurationsoptionen
    enableDebugMode := false
    allowGuestAccess := true
    useHttps := true

    // Bedingungen und Flags
    foundError := false
    needsUpdate := true
    canProceed := isLoggedIn && hasPermission && !foundError

    fmt.Printf("Kann fortfahren: %t\n", canProceed)

    // Funktionsergebnisse
    success := processData
    if success {
        fmt.Printf("Datenverarbeitung erfolgreich")
    } else {
        fmt.Printf("Fehler bei der Datenverarbeitung")
    }
}

Logische Operatoren

AND-Operator (&&)

Der AND-Operator && gibt true zurück, wenn beide Operanden true sind. Go verwendet “short-circuit evaluation”, was bedeutet, dass der zweite Operand nicht ausgewertet wird, wenn der erste bereits false ist.

Go Beispiel
package main

import "fmt"

func expensiveOperation() bool {
    fmt.Println("Diese Operation wurde ausgeführt")
    return true
}

func main() {

    // Grundlegende AND-Operationen
    fmt.Printf("true && true = %t\n", true && true)
    fmt.Printf("true && false = %t\n", true && false)
    fmt.Printf("false && true = %t\n", false && true)
    fmt.Printf("false && false = %t\n", false && false)

    userLoggedIn := true
    hasAdminRights := false

    canAccessAdminPanel := userLoggedIn && hasAdminRights
    fmt.Printf("Zugang zum Admin: %t\n", canAccessAdminPanel)

    // Short-circuit evaluation
    fmt.Println("\nShort-circuit evaluation")
    result := false && expensiveOperation()
    fmt.Printf("Ergebnis: %t\n", result)

}
Output
true && true = true
true && false = false
false && true = false
false && false = false
Zugang zum Admin: false

Short-circuit evaluation
Ergebnis: false

OR-Operator (||)

Der OR-Operator || gibt true zurück, wenn mindestens einer der Operanden true ist. Auch hier wird short-circuit evaluation angewendet - der zweite Operand wird nicht ausgewertet, wenn der erste bereits true ist.

Go Beispiel
package main

import "fmt"

func main() {

    // Grundlegende OR-Operationen
    fmt.Printf("true || true = %t\n", true || true)
    fmt.Printf("true || false = %t\n", true || false)
    fmt.Printf("false || true = %t\n", false || true)
    fmt.Printf("false || false = %t\n", false || false)

    isWeekend := false
    isHoliday := true

    canRelax := isWeekend || isHoliday
    fmt.Printf("Kann entspannen: %t\n", canRelax)

    // Mehrere OR-Verknüpfungen
    hasCard := false
    hasCash := true
    hasDigitalWallet := false

    canPay := hasCard || hasCash || hasDigitalWallet
    fmt.Printf("Kann bezahlen: %t\n", canPay)

}
Output
true || true = true
true || false = true
false || true = true
false || false = false
Kann entspannen: true
Kann bezahlen: true

NOT-Operator (!)

Der NOT-Operator ! invertiert den Wahrheitswert seines Operanden. true wird zu false und false wird zu true.

Go Beispiel
package main

import "fmt"

func main() {

    // Grundlegende NOT-Operationen
    fmt.Printf("!true = %t\n", !true)
    fmt.Printf("!false = %t\n", !false)

    // Doppelte Negation
    originalValue := true
    doubleNegated := !!originalValue
    fmt.Printf("!!true = %t\n", doubleNegated)

    isConnected := false
    isDisconnected := !isConnected
    fmt.Printf("Verbindung getrennt: %t\n", isDisconnected)

    // In Bedingungen
    isVisible := true
    if !isVisible {
        fmt.Println("Element ist nicht sichtbar")
    } else {
        fmt.Println("Element ist sichtbar")
    }

    // Negation komplexer Ausdrücke
    hasError := false
    isReady := true
    canProceed := !(hasError || !isReady)
    fmt.Printf("Kann fortfahren: %t\n", canProceed)

}
Output
!true = false
!false = true
!!true = true
Verbindung getrennt: true
Element ist sichtbar
Kann fortfahren: true

Typkonvertierung

Explizite Konvertierung

Go erlaubt keine implizite Konvertierung zwischen Boolean-Werten und anderen Typen. Alle Konvertierungen müssen explizit durchgeführt werden.

Go Beispiel
package main

import (
    "fmt"
    "strconv"
)

func main() {

    // Boolean zu String
    boolValue := true

    // Verwendung von fmt.Sprintf
    stringValue := fmt.Sprintf("%t", boolValue)
    fmt.Printf("Boolean als String: '%s'\n", stringValue)

    // Verwendung von strconv.FormatBool
    stringValue2 := strconv.FormatBool(boolValue)
    fmt.Printf("Mit strconv: '%s'\n", stringValue2)

    // String zu Boolean
    stringInput := "true"
    if boolResult, err := strconv.ParseBool(stringInput); err == nil {
        fmt.Printf("String '%s' als Boolean: %t\n", stringInput, boolResult)
    }

    // ParseBool() akzeptiert verschiedene Formate
    testStrings := []string{
        "true",
        "false",
        "1",
        "0",
        "t",
        "f",
        "T",
        "F",
        "TRUE",
        "FALSE",
    }

    for _, s := range testStrings {
        if b, err := strconv.ParseBool(s); err == nil {
            fmt.Printf("'%s' => %t\n", s, b)
        } else {
            fmt.Printf("'%s' => Fehler: %v\n", s, err)
        }
    }

}
Output
Boolean als String: 'true'
Mit strconv: 'true'
String 'true' als Boolean: true
'true' => true
'false' => false
'1' => true
'0' => false
't' => true
'f' => false
'T' => true
'F' => false
'TRUE' => true
'FALSE' => false

Boolean zu Integer

Da Go keine direkte Konvertierung von Boolean zu Integer erlaubt, muss dies manuell implementiert werden.

Go Beispiel
package main

import "fmt"

func boolToInt(b bool) int {
    if b {
        return 1
    }
    return 0
}

func intToBool(i int) bool {
    return i != 0
}

func main() {
    // Boolean zu Integer
    trueValue := true
    intValue := boolToInt(trueValue)
    fmt.Printf("Boolean %t als Integer: %d\n", trueValue, intValue)

    falseValue := false
    intValue2 := boolToInt(falseValue)
    fmt.Printf("Boolean %t als Integer: %d\n", falseValue, intValue2)

    // Integer zu Boolean
    nums := []int{0, 1, -1, 42, 0}
    for _, num := range nums {
        boolRes := intToBool(num)
        fmt.Printf("Integer %d als Boolean: %t\n", num, boolRes)
    }
}
Output
Boolean true als Integer: 1
Boolean false als Integer: 0
Integer 0 als Boolean: false
Integer 1 als Boolean: true
Integer -1 als Boolean: true
Integer 42 als Boolean: true
Integer 0 als Boolean: false

Häufige Stolperfallen

Kein impliziter Cast von int zu bool.

Anders als in C oder Python ist bool in Go ein eigenständiger, nicht-numerischer Typ. if x mit x int kompiliert nicht — du brauchst if x != 0. Genauso wenig kannst du bool(1) schreiben oder einen bool direkt addieren. Konvertierungen sind immer manuell über eine Hilfsfunktion zu lösen.

&& und || sind kurzschließend.

Der zweite Operand wird nur ausgewertet, wenn der erste das Ergebnis nicht bereits festlegt. Das ist nützlich für Idiome wie if p != nil && p.Valid() — aber gefährlich, wenn der zweite Operand Seiteneffekte hat, auf die du dich verlässt. Wenn beide Funktionen unbedingt laufen müssen, werte sie vorher in zwei bool-Variablen aus.

== vergleicht Werte, nicht Identitäten.

Bei bool ist das selten ein Problem, aber bei Typen, die sich implizit nach bool lesen lassen (z. B. das ok-Pattern bei m[k] oder Type Assertions), wird gerne übersehen, dass ok == true und ok semantisch gleichwertig sind. Idiomatisch ist if ok { ... } — der explizite Vergleich == true gilt als Code-Smell.

Zero-Value ist false.

Eine nicht initialisierte bool-Variable, ein bool-Feld in einem Struct oder ein Element in einem []bool enthält immer false. Das ist meist erwünscht, kann aber Bugs verstecken: Du kannst nicht unterscheiden, ob ein Wert nie gesetzt wurde oder explizit auf false gesetzt wurde. Wenn diese Unterscheidung wichtig ist, nimm *bool oder ein zusätzliches Flag.

Negationen erschweren die Lesbarkeit.

Ausdrücke wie !isInvalid oder !(hasError || !isReady) sind zwar korrekt, aber kognitiv teuer. Benenne deine Booleans positiv (isValid statt isInvalid), und ziehe Zwischenvariablen heraus, sobald die Negationstiefe größer als eins wird.

strconv.ParseBool akzeptiert mehr als "true"/"false".

Auch "1", "0", "t", "T", "f", "F", "TRUE", "FALSE", "True" und "False" sind gültig — alles andere liefert einen *NumError. Wer eine strikte Eingabevalidierung braucht, sollte selbst prüfen statt blind ParseBool zu vertrauen. Insbesondere "yes"/"no" werden nicht erkannt.

fmt.Printf("%t", b) und strconv.FormatBool(b) liefern dasselbe.

Beide geben "true" oder "false" zurück — kleingeschrieben, ohne Anführungszeichen. Wenn du andere Darstellungen brauchst (z. B. "ja"/"nein"), musst du selbst formatieren.

Weiterführende Ressourcen

Externe Quellen

/ Weiter

Zurück zu Datentypen

Zur Übersicht