---
title: "Типы данных: bool и логика"
description: "Тип bool в Go: истина и ложь, операторы сравнения, логические операторы &&, ||, ! и сокращённые вычисления. Примеры с запуском в браузере и типичные ошибки."
course: "Go с нуля: базовый синтаксис и конструкции"
url: "https://golangmaster.ru/courses/go-basics/lessons/07-bool-i-logika/"
published: "2026-09-19"
updated: "2026-09-28"
minutes: 15
---

# Типы данных: bool и логика

*Курс «Go с нуля: базовый синтаксис и конструкции», урок 7 из 25. ~15 минут. Обновлено 28.09.2026. Источник: https://golangmaster.ru/courses/go-basics/lessons/07-bool-i-logika/*

Тип bool в Go принимает ровно два значения — true и false — и не даёт себе ни единой вольности: ноль не станет ложью, пустая строка не станет истиной, а логические операторы &&, || и ! останавливаются, как только ответ ясен. Разберём сравнения, таблицы истинности, сокращённые вычисления и ситуации, в которых новичок обычно теряет компиляцию.

### bool: только истина и ложь, ничего лишнего

Логический тип — самый маленький в языке: `b := true` создаёт bool, у которого ровно два значения. Нулевое значение — `false`, что логично: пока вы явно не сказали «да», мир по умолчанию говорит «нет». Даже не объявляйте пустые булевы переменные «на всякий случай» — они молча будут false, и условие, которое вы забыли заполнить, просто никогда не сработает.

Главная особенность по сравнению с JavaScript, Python или C: в Go между числами и логикой нет моста. `if 1` не скомпилируется, `bool(0)` не соберётся, а присваивание `flag := 1` в условии выдаст ошибку о несовпадении типов. Мнение, которое я слышу от новичков постоянно: «зачем столько строгости, в Python это удобно». В маленьких скриптах — возможно. В серверном коде, где условие пишут восемь человек в год, запрет молчаливых истин спасает от целого класса багов: нулевой id не притворится «нет результата», пустая строка не притворится «не найдено». Каждое превращение значения в решение должно быть написано руками — и потому видно в ревью.

### Операторы сравнения: откуда берётся bool

| Оператор | Смысл | Пример | Результат |
| --- | --- | --- | --- |
| == | равно | 5 == 5 | true |
| != | не равно | 5 != 3 | true |
| < | меньше | 3 < 2 | false |
| > | больше | 3 > 2 | true |
| <= | меньше или равно | 3 <= 3 | true |
| >= | больше или равно | 2 >= 3 | false |

### Сравнение чисел и строк

Сравнение — главный поставщик булевых значений: любой из шести операторов из таблицы, применённый к числам, возвращает bool. Строки сравниваются теми же операторами: равенство `"Go" == "go"` даёт false — регистр важен, а `"apple" < "banana"` даёт true, потому что сравнение идёт по байтам, а латинская a стоит в таблице раньше b. С кириллицей порядок тоже честный: в UTF-8 порядок байт совпадает с порядком символов, поэтому алфавитные сравнения работают, что мы подробно разбирали в уроке про [строки и руны](/courses/go-basics/lessons/06-stroki-i-runes/).

Две ловушки. Первая: нельзя писать «цепочки» как в математике — `0 < x < 10` не скомпилируется, потому что первое сравнение вернёт bool, а bool с числом сравнивать нельзя; пишите `0 < x && x < 10`. Вторая: операторы == и != работают для строк, чисел и указателей, но для срезов и карт их применять нельзя — компилятор ответит ошибкой; срезы сравнивают циклом по элементам, функцией slices.Equal или reflect.DeepEqual. Базовый случай — скаляры — запомните, до срезов ещё дойдём.

### Песочница: сравнения и отрицание

Запустите и сверьте все четыре строки вывода. Затем измените temp на 18: третья строка станет false, а четвёртая останется true — потому что || спасает положение, когда первое условие провалилось.

```go
package main

import "fmt"

func main() {
        temp := 25
        sunny := true
        fmt.Println(temp > 20, temp == 25, temp != 25)
        fmt.Println(sunny, !sunny)
        fmt.Println(temp > 20 && sunny)
        fmt.Println(temp < 20 || sunny)
}
```

### Логические операторы go: и, или, не

Три оператора комбинируют булевы значения. И — `&&` (два амперсанда): истина, только когда истинны оба операнда. ИЛИ — `||` (две вертикальные черты): ложь, только когда ложны оба. НЕ — `!` (восклицательный знак): переворачивает значение. Приоритет у `!` самый высокий, затем `&&`, затем `||` — как в арифметике умножение старше сложения, о чём подробнее в уроке про [операторы и выражения](/courses/go-basics/lessons/08-operatory/).

Читаются выражения вслух почти дословно: `age >= 18 && hasTicket` — «возраст не меньше восемнадцати И есть билет». Составные условия из двух-трёх частей читаются хорошо, а вот пять операторов подряд — уже паранойя: выносите промежуточный результат в переменную с говорящим именем `canEnter` или `isWorkingDay`. Компилятору всё равно, а человеку через полгода — нет.

### Таблица истинности && и ||

| A | B | A && B | A || B |
| --- | --- | --- | --- |
| true | true | true | true |
| true | false | false | true |
| false | true | false | true |
| false | false | false | false |

### Проверьте себя: приоритет и и или

**Вопрос:** Что напечатает `fmt.Println(true || false && false)`?

- ✅ true
- false
- ошибка компиляции
- true и false

&& связывает крепче, чем ||: выражение группируется как true || (false && false), то есть true || false — истина. Если бы && вычислялся первым по-другому, ответ мог бы измениться, поэтому в спорных местах ставьте скобки, даже когда помните приоритет.

### Сокращённые вычисления: правая часть не всегда считается

У && и || есть свойство, которого нет у арифметики: если ответ уже ясен из левой части, правая просто не вычисляется. Для && достаточно ложного левого операнда — результат ложь в любом случае. Для || достаточно истинного — результат истина. Это называется сокращёнными вычислениями (short-circuit evaluation), и на этом свойстве держится половина идиом Go.

Самая важная — защитное условие. Сначала проверяем, что значение вообще существует, и только потом работаем с его содержимым: `if user != nil && user.Age > 18` — если user пуст, второй операнд не вычислится и программа не упадёт. Поменяйте операнды местами — и при пустом user проверка Age станет паникой. Порядок в && — это не стиль, а безопасность.

Второе применение — экономные проверки: `len(s) > 0 && s[0] == '#'` не полезет за индексом в пустую строку. Функции с побочными эффектами (логирование, счётчики) внутри таких выражений ведут себя коварно: они просто не вызовутся, если левая часть решила всё — не полагайтесь на «вызов точно случится».

### Наблюдаем сокращённые вычисления

```go
package main

import "fmt"

func fails(name string) bool {
        fmt.Println("вызвана", name)
        return false
}

func ok(name string) bool {
        fmt.Println("вызвана", name)
        return true
}

func main() {
        fmt.Println(fails("первая") && ok("вторая"))
        fmt.Println(ok("третья") || ok("четвёртая"))
}
```

В первой строке fails("первая") вернула false, и && даже не потревожил ok("вторая") — в выводе нет «вызвана вторая». Во второй строке ok("третья") вернула true, и || пропустил четвёртую. Функции-свидетели наглядно показывают, кто вычислялся, а кого пропустили.

### Что выведет код?

```go
package main

import "fmt"

func main() {
        login := ""
        fmt.Println(login != "" && len(login) > 3)
        fmt.Println(login == "" || len(login) > 3)
}
```

**Что выведет программа?**

- ✅ false и true
- true и false
- false и false
- ошибка: пустая строка без len

login — пустая строка. Первое выражение: login != "" ложно, && останавливается — false, до len дело не доходит. Второе: login == "" истинно, || останавливается — true. Классическая пара проверок: сначала «поле заполнено», затем «в поле достаточно символов».

> **True с заглавной буквы не существует.** В Go логические литералы пишутся строго маленькими буквами: true и false. True, FALSE и True — это неизвестные имена, компилятор ответит undefined. Привычка из Python (True/False) или C++ (TRUE) здесь работает против вас: язык регистрозависим, и это распространяется на все ключевые слова.

### Где bool живёт в настоящем коде

Булевы значения в Go — это не абстракция про философию, а рабочий инструмент с конкретными гнёздами. Условия `if` и `for` принимают только bool — никаких «непустая строка значит истина». Функции пакетов возвращают bool постоянно: `strings.Contains` отвечает, есть ли подстрока, `strings.HasPrefix` — начинается ли строка с префикса. Позже вы встретите ok-форму: чтение из карты и проверка типа возвращают значение и bool-флаг «получилось ли» — это одна из самых узнаваемых идиом языка.

Переменным-флагам давайте имена-утверждения: `isValid`, `hasPermission`, `isPaid` — читаются в if как предложения. Имена вроде `flag` или `check` ничего не сообщают: флаг чего, проверка чего? Мелочь, на которую уходит десять секунд при написании, а экономит она минуты при чтении чужого кода — и своего тоже.

### Соберите условие входа

Заполните пропуски операторами так, чтобы canEnter был истинным, только когда возраст не меньше 18 И билет есть.

```go
package main

import "fmt"

func main() {
        age := 20
        hasTicket := true
        canEnter := age ___ 18 ___ hasTicket
        fmt.Println(canEnter)
}
```

Подсказка: Первый пропуск — оператор сравнения «больше или равно». Второй — логическое И, два амперсанда без пробелов.

Правильные ответы в пропусках: `>=`, `&&`

### Карточки: bool и логика

- **Нулевое значение bool** — false. Объявленная, но не инициализированная булева переменная молча равна false.
- **Станет ли if 1 истиной, как в C?** — Нет. Условие в if и for принимает только bool; число без сравнения не компилируется.
- **Приоритет !, && и ||** — Сначала !, потом &&, потом ||. Скобки в смешанных выражениях — не роскошь, а самодокументация.
- **Что такое сокращённые вычисления?** — && не вычисляет правую часть при ложной левой, || — при истинной. Основа защитных условий вида user != nil && user.Age > 0.
- **Почему в && порядок операндов важен?** — Левый операнд вычисляется первым и защищает правый: сначала проверка существования, потом использование значения.
- **Как правильно пишутся литералы?** — Только true и false, с маленькой буквы. True и FALSE — ошибки компиляции.

## Коротко: что запомнить

- bool имеет ровно два значения: true и false; нулевое значение — false.
- Числа и строки не превращаются в bool сами: строгий if без truthiness.
- Шесть операторов сравнения (==, !=, <, >, <=, >=) — главный источник булевых значений.
- && истинно только при обоих истинных, || ложно только при обоих ложных, ! переворачивает.
- Приоритет: ! выше &&, && выше ||; спорные выражения проясняйте скобками.
- Сокращённые вычисления пропускают правую часть — на этом держатся защитные условия.
- Порядок в && — безопасность: сначала «значение есть», затем работа с ним.

## Домашнее задание

Напишите программу с тремя переменными: age := 16, hasTicket := true, isVip := false. Выведите построчно: допущен ли человек на вечернее мероприятие (age >= 18 && hasTicket), пускают ли с VIP-билетом без проверки возраста (isVip || age >= 18) и отрицание VIP-статуса (!isVip). Ожидание для шестнадцатилетнего: false, false, true. Затем измените age на 19 и убедитесь, что первые две строки переключились на true, а третья не тронулась — отрицание от возраста не зависит.

## Вопросы и ответы по уроку

### Почему в Go нет truthiness, как в Python?

Авторы языка сознательно запретили неявное превращение чисел и строк в истину или ложь: условие должно быть честным bool. Это устраняет целый класс ошибок, где 0 или "" случайно считались «ложью» с неожидаемым поведением, и делает чтение условий однозначным.

### Чем && отличается от & (одинарный)?

Одиночный & — это побитовое И для чисел и взятие адреса переменной, а не логический оператор. Для логики всегда пишите двойной && (и двойной || для ИЛИ): сокращённые вычисления есть только у двойных операторов.

### Можно ли складывать булевы значения или сравнивать их?

Арифметика с bool запрещена — язык не даст превратить true в 1. Сравнивать bool операторами == и != формально можно, но в живом коде это почти всегда признак лишнего условия: вместо flag == true пишите просто flag.
