Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 8

Управляющие конструкции в программировании

Recommended resources

Здравствуйте!

На прошлом уроке мы разобрались, как работать с функциями как с объектами первого класса и как использовать замыкания для создания функций с состоянием. Это мощные концепции, которые позволяют писать гибкий и выразительный код.

Сегодня мы переходим к строительным блокам любой программы — управляющим конструкциям. Цель этого урока — научиться реализовывать ветвление и циклы с помощью if, switch и различных форм for. Хотя сами идеи ветвлений и циклов вам прекрасно знакомы из JavaScript, в Go есть свои синтаксические особенности и идиомы, которые делают код более читаемым и безопасным. Мы сосредоточимся именно на этих отличиях и на том, как писать код в стиле Go.

Ветвление с if-else

Конструкция if-else в Go служит той же цели, что и в других языках, но имеет два ключевых синтаксических отличия:

  1. Скобки вокруг условия не ставятся: if x > 0 вместо if (x > 0).
  2. Фигурные скобки {} обязательны всегда, даже для тела из одной строки. Это предотвращает ошибки, характерные для C-подобных языков (например, знаменитая уязвимость Apple goto 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:

  1. С тремя компонентами (как в C/JavaScript): for i := 0; i < 10; i++ { ... }
  2. Только с условием (аналог while): for sum < 1000 { ... }
  3. Без условия (бесконечный цикл): 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.

Effective Go

Прочитайте раздел о 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

Теперь прочитайте соответствующий раздел в 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.