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.
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)
}isValid: false
isReady: true
isComplete: false
isActive: true isEnabled: falseZero-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.
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)
}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.
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)
}Wahr: true, Falsch: false
true AND false = false
true OR false = true
NOT true = falseSemantische 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.
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.
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)
}true && true = true
true && false = false
false && true = false
false && false = false
Zugang zum Admin: false
Short-circuit evaluation
Ergebnis: falseOR-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.
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)
}true || true = true
true || false = true
false || true = true
false || false = false
Kann entspannen: true
Kann bezahlen: trueNOT-Operator (!)
Der NOT-Operator ! invertiert den Wahrheitswert seines Operanden. true wird zu false und false wird zu true.
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)
}!true = false
!false = true
!!true = true
Verbindung getrennt: true
Element ist sichtbar
Kann fortfahren: trueTypkonvertierung
Explizite Konvertierung
Go erlaubt keine implizite Konvertierung zwischen Boolean-Werten und anderen Typen. Alle Konvertierungen müssen explizit durchgeführt werden.
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)
}
}
}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' => falseBoolean zu Integer
Da Go keine direkte Konvertierung von Boolean zu Integer erlaubt, muss dies manuell implementiert werden.
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)
}
}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: falseHä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
- Boolean types – Go Language Specification
- Logical operators – Go Specification
- Paket
strconv– pkg.go.dev