Содержание урока · 10 разделов
- bool: только истина и ложь, ничего лишнего
- Операторы сравнения: откуда берётся bool
- Сравнение чисел и строк
- Логические операторы go: и, или, не
- Таблица истинности && и ||
- Сокращённые вычисления: правая часть не всегда считается
- Где bool живёт в настоящем коде
- Песочница урока
- Коротко: что запомнить
- Вопросы и ответы
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 порядок байт совпадает с порядком символов, поэтому алфавитные сравнения работают, что мы подробно разбирали в уроке про строки и руны.
Две ловушки. Первая: нельзя писать «цепочки» как в математике — 0 < x < 10 не скомпилируется, потому что первое сравнение вернёт bool, а bool с числом сравнивать нельзя; пишите 0 < x && x < 10. Вторая: операторы == и != работают для строк, чисел и указателей, но для срезов и карт их применять нельзя — компилятор ответит ошибкой; срезы сравнивают циклом по элементам, функцией slices.Equal или reflect.DeepEqual. Базовый случай — скаляры — запомните, до срезов ещё дойдём.
Песочница: сравнения и отрицание
Запустите и сверьте все четыре строки вывода. Затем измените temp на 18: третья строка станет false, а четвёртая останется true — потому что || спасает положение, когда первое условие провалилось.
Запустите код, чтобы увидеть вывод.
Логические операторы go: и, или, не#
Три оператора комбинируют булевы значения. И — && (два амперсанда): истина, только когда истинны оба операнда. ИЛИ — || (две вертикальные черты): ложь, только когда ложны оба. НЕ — ! (восклицательный знак): переворачивает значение. Приоритет у ! самый высокий, затем &&, затем || — как в арифметике умножение старше сложения, о чём подробнее в уроке про операторы и выражения.
Читаются выражения вслух почти дословно: 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)`?
Сокращённые вычисления: правая часть не всегда считается#
У && и || есть свойство, которого нет у арифметики: если ответ уже ясен из левой части, правая просто не вычисляется. Для && достаточно ложного левого операнда — результат ложь в любом случае. Для || достаточно истинного — результат истина. Это называется сокращёнными вычислениями (short-circuit evaluation), и на этом свойстве держится половина идиом Go.
Самая важная — защитное условие. Сначала проверяем, что значение вообще существует, и только потом работаем с его содержимым: if user != nil && user.Age > 18 — если user пуст, второй операнд не вычислится и программа не упадёт. Поменяйте операнды местами — и при пустом user проверка Age станет паникой. Порядок в && — это не стиль, а безопасность.
Второе применение — экономные проверки: len(s) > 0 && s[0] == '#' не полезет за индексом в пустую строку. Функции с побочными эффектами (логирование, счётчики) внутри таких выражений ведут себя коварно: они просто не вызовутся, если левая часть решила всё — не полагайтесь на «вызов точно случится».
Наблюдаем сокращённые вычисления
GOpackage 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)
}В 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 И билет есть.
Карточки: bool и логика
Песочница урока
Редактируйте код и запускайте его прямо здесь — интерпретатор работает в браузере, ничего устанавливать не нужно. За каждый запуск — +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 нет truthiness, как в Python?
Авторы языка сознательно запретили неявное превращение чисел и строк в истину или ложь: условие должно быть честным bool. Это устраняет целый класс ошибок, где 0 или "" случайно считались «ложью» с неожидаемым поведением, и делает чтение условий однозначным.
Чем && отличается от & (одинарный)?
Одиночный & — это побитовое И для чисел и взятие адреса переменной, а не логический оператор. Для логики всегда пишите двойной && (и двойной || для ИЛИ): сокращённые вычисления есть только у двойных операторов.
Можно ли складывать булевы значения или сравнивать их?
Арифметика с bool запрещена — язык не даст превратить true в 1. Сравнивать bool операторами == и != формально можно, но в живом коде это почти всегда признак лишнего условия: вместо flag == true пишите просто flag.
Термины урока
Ключевые понятия из этого урока — короткие определения в глоссарии. Наведите на термин, чтобы вспомнить, откройте карточку для подробностей и ссылки на практику.
Изучайте дальше
Следующая ступень учебного пути
Продвинутые возможности Go: от замыканий до рефлексии
Продвинутый курс Go: замыкания, defer, горутины, каналы, контекст, интерфейсы, дженерики, рефлексия, тесты и JSON. 25 уроков с практикой в браузере.
- Писать и читать конкурентный код: go-функции, каналы, select
- Управлять жизненным циклом операций через context
- Проектировать API на интерфейсах
- Использовать дженерики без злоупотребления