Здравствуйте!
На прошлом уроке мы разобрались, как работать с функциями как с объектами первого класса и как использовать замыкания для создания функций с состоянием. Это мощные концепции, которые позволяют писать гибкий и выразительный код.
Сегодня мы переходим к строительным блокам любой программы — управляющим конструкциям. Цель этого урока — научиться реализовывать ветвление и циклы с помощью if, switch и различных форм for. Хотя сами идеи ветвлений и циклов вам прекрасно знакомы из JavaScript, в Go есть свои синтаксические особенности и идиомы, которые делают код более читаемым и безопасным. Мы сосредоточимся именно на этих отличиях и на том, как писать код в стиле Go.
Ветвление с if-else
Конструкция if-else в Go служит той же цели, что и в других языках, но имеет два ключевых синтаксических отличия:
- Скобки вокруг условия не ставятся:
if x > 0вместоif (x > 0). - Фигурные скобки
{}обязательны всегда, даже для тела из одной строки. Это предотвращает ошибки, характерные для C-подобных языков (например, знаменитая уязвимость Applegoto fail;).
Более интересная особенность — это if с коротким стейтментом (short statement). Он позволяет объявить и инициализировать переменные, область видимости которых ограничена только блоком if-else. Это очень идиоматичный для Go прием, особенно при обработке ошибок.
Давайте посмотрим на эти конструкции в действии.
Изучаем Golang. Урок 2. Основы. Продолжение. Циклы, ветвления
Посмотрите фрагмент видео из канала "The Art of Development", где автор объясняет основы ветвления.
Обратите внимание на: Базовый синтаксис if-else в примере. Сокращение кода, когда if содержит return, что избавляет от необходимости писать else (этот паттерн). Наиболее важная часть: if с инициализацией. Автор наглядно показывает, как можно объявить переменную прямо внутри условия и как это влияет на ее область видимости.
Как вы видели, идиома if err := someFunc(); err != nil встречается в Go повсеместно. Она позволяет держать логику обработки ошибок рядом с вызовом, который может их сгенерировать, и не "загрязнять" внешнюю область видимости переменной err. Это делает поток управления основного, успешного сценария более линейным и читаемым.
Циклы: один for для всего
В отличие от JavaScript, где есть for, while, do-while, for...in и for...of, в Go есть только одна циклическая конструкция — for. Однако она достаточно гибкая, чтобы покрыть все эти сценарии.
Существуют три основные формы for:
- С тремя компонентами (как в C/JavaScript):
for i := 0; i < 10; i++ { ... } - Только с условием (аналог
while):for sum < 1000 { ... } - Без условия (бесконечный цикл):
for { ... }
Посмотрите, как эти формы демонстрируются в следующем видеофрагменте.
Изучаем Golang. Урок 2. Основы. Продолжение. Циклы, ветвления
В этом видео разбираются все варианты цикла for.
Просмотрите следующие части: Классический цикл for с инициализацией, условием и постинкрементом. Цикл с условием, который работает как while в других языках. Бесконечный цикл и его синтаксис.
Итерация с for...range
Самый распространенный способ итерировать по коллекциям (массивам, срезам, строкам, map и каналам) в Go — это конструкция for...range. Она похожа на for...of в JavaScript, но возвращает два значения: индекс и сам элемент.
numbers := []int{10, 20, 30}
for index, value := range numbers {
fmt.Printf("Index: %d, Value: %d\n", index, value)
}
Если вам не нужен индекс или значение, вы можете использовать пустой идентификатор _.
// Нужен только value
for _, value := range numbers {
fmt.Println(value)
}
// Нужен только index
for index := range numbers {
fmt.Println(index)
}
Давайте изучим официальную документацию Effective Go, чтобы закрепить понимание for...range.
Прочитайте раздел о for в Effective Go, чтобы увидеть идиоматическое использование range.
В секции "For" найдите подраздел, начинающийся со слов "If you're looping over an array...". Прочтите этот фрагмент, обращая особое внимание на: Синтаксис for key, value := range .... Использование _ (blank identifier) для отбрасывания ненужных значений. Пример итерации по строке, где range корректно обрабатывает UTF-8 символы (руны).
switch: мощнее, чем кажется
Конструкция switch в Go — это еще один пример, где язык предлагает более мощный и безопасный инструмент по сравнению с его аналогами в C-семействе.
Ключевые отличия от JavaScript:
breakне нужен. Выполнение не "проваливается" (fallthrough) в следующийcaseавтоматически. Если такое поведение нужно, используется ключевое словоfallthrough.caseмогут быть не только константами. Условия вcaseмогут быть выражениями, которые вычисляются во время выполнения.switchбез выражения. Можно написатьswitch { ... }, и он будет работать как более чистая и читаемая замена для цепочкиif-else if-else.
Давайте сначала посмотрим базовый синтаксис.
Изучаем Golang. Урок 2. Основы. Продолжение. Циклы, ветвления
В этом заключительном фрагменте автор вводит switch как альтернативу множеству if.
Смотрите внимательно: Базовый switch по переменной. switch с инициализацией, аналогично if. switch без переменной, где условия указываются прямо в case.
Последний вариант, switch без выражения, особенно полезен и широко используется в Go для организации чистой логики ветвления.
Теперь прочитайте соответствующий раздел в Effective Go, чтобы увидеть канонические примеры использования switch.
В секции "Switch" прочитайте от начала и до конца этого примера. Сосредоточьтесь на: Использовании switch без выражения (tagless switch) как идиоматичной замены if-else. Объединении нескольких условий в одном case через запятую.
Итоги
Сегодня мы освоили базовые управляющие конструкции Go, отметив их ключевые отличия от того, к чему вы привыкли в JavaScript.
if: Не требует()вокруг условия, но{}обязательны. Идиоматично использоватьifс коротким стейтментом (if x := f(); x > 0) для ограничения области видимости.for: Единственная конструкция для циклов в Go, но она может работать как классическийfor,whileи бесконечный цикл.for...range: Основной способ итерации по коллекциям, возвращающийиндекс, значение. Пустой идентификатор_используется для игнорирования ненужных частей.switch: Более гибкий и безопасный, чем в C/JavaScript. Не требуетbreak(нет автоматического fallthrough),caseмогут быть выражениями, аswitchбез условия — это элегантная заменаif-elseцепочкам.
Эти конструкции являются фундаментом для построения логики программы. Уверенное владение их идиоматическим применением — важный шаг к написанию чистого и эффективного Go-кода.
В следующем уроке мы погрузимся в мир составных типов данных Go и начнем с массивов и срезов (slices). Мы разберемся в их семантике, отличиях и научимся эффективно ими управлять, используя в том числе и циклы for...range.