Перейти к содержимому
ГоМастер

Поиск по урокам

Найдите урок, курс, термин или раздел

Урок 7 из 25 ~15 мин +50 XP

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

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

Содержание урока · 10 разделов

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

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

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

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

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

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

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

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

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

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

Вывод

Запустите код, чтобы увидеть вывод.

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

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

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

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

ABA && BA || B
truetruetruetrue
truefalsefalsetrue
falsetruefalsetrue
falsefalsefalsefalse

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

Что напечатает `fmt.Println(true || false && 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, и || пропустил четвёртую. Функции-свидетели наглядно показывают, кто вычислялся, а кого пропустили.

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

Прочитайте код и выберите, что он выведет:

package main

import "fmt"

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

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

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

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

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

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

package main import "fmt" func main() { age := 20 hasTicket := true canEnter := age 18 hasTicket fmt.Println(canEnter) }

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

Термин

Нулевое значение bool

нажмите, чтобы перевернуть
Определение

false. Объявленная, но не инициализированная булева переменная молча равна false.

1 / 6

Песочница урока

Редактируйте код и запускайте его прямо здесь — интерпретатор работает в браузере, ничего устанавливать не нужно. За каждый запуск — +2 XP.

Вывод

Запустите код, чтобы увидеть вывод.

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

  • 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 Base · Типы данных: bool и логика)

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

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

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

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

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

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

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

Термины урока

Ключевые понятия из этого урока — короткие определения в глоссарии. Наведите на термин, чтобы вспомнить, откройте карточку для подробностей и ссылки на практику.

Следующая ступень учебного пути

Go Pro25 уроков~14 чпрактика25 уроков уже доступны

Продвинутые возможности Go: от замыканий до рефлексии

Продвинутый курс Go: замыкания, defer, горутины, каналы, контекст, интерфейсы, дженерики, рефлексия, тесты и JSON. 25 уроков с практикой в браузере.

  • Писать и читать конкурентный код: go-функции, каналы, select
  • Управлять жизненным циклом операций через context
  • Проектировать API на интерфейсах
  • Использовать дженерики без злоупотребления