Управление потоком
Go сознательно держит набор управляющих конструкций маленьким: одно условие if, один цикл for, один switch и пара panic/recover для исключительных ситуаций. Скобки вокруг условий не нужны, фигурные скобки обязательны всегда, а for — единственная форма цикла в языке: ни while, ни do-while нет, всё выражается через него.
За этой простотой прячутся отличия, которые и проверяют на junior-секции: if и switch умеют нести init-выражение с собственной областью видимости; switch в Go не проваливается между case по умолчанию (нужен явный fallthrough); range отдаёт пары вроде «индекс, значение» и переиспользует переменную цикла; а recover работает только внутри отложенной функции. Тема разбирает поток выполнения по слоям — от ветвлений до перехвата паники.
Карта темы
- Условия:
if/else—if/else/else ifбез скобок вокруг условия и с обязательными{}; необязательное init-выражениеif x := f(); x > 0 {…}живёт только внутриif. - Цикл
for— единственный цикл Go в трёх формах (C-стиль с тремя частями,for condвместоwhile, бесконечныйfor {});break/continueи метки. switch— выбор по значению с несколькими значениями наcase, без неявного проваливания (fallthroughявный), безвыражённыйswitch {}как цепочкаif-elseи необязательное init-выражение.range— перебор слайса/массива (индекс, значение),map(ключ, значение), строки (индекс байта, руна) и канала (полученное значение);_отбрасывает ненужное.panicиrecover—panicраскручивает стек, выполняя отложенные функции;recoverловит панику только внутриdefer; это для исключительных случаев, а не для обычных ошибок.
Частые ошибки и ловушки
| Ошибка | Последствие |
|---|---|
Писать if (cond) {…} со скобками, как в C | Скобки лишние и не идиоматичны; gofmt их не уберёт, но линтер отметит |
Опускать {} для однострочного if | Не компилируется — фигурные скобки в Go обязательны всегда |
Использовать переменную из if x := f(); … после if | x видна только внутри if/else; снаружи — ошибка компиляции |
Ждать проваливания из одного case в следующий, как в C | В Go case не проваливается по умолчанию; нужен явный fallthrough |
Ставить break в конце каждого case по привычке | Лишний break — Go выходит из switch сам после case |
Брать адрес переменной цикла range и сохранять его | Переменная переиспользуется между итерациями — все указатели смотрят на одно значение |
Вызывать recover() напрямую в теле функции, а не в defer | Вне отложенной функции recover вернёт nil и панику не остановит |
Значение для собеседований
Управляющие конструкции — это junior-фильтр на «знает синтаксис Go» против «переносит привычки из C/Java». Сами по себе они тривиальны, но отличия от других языков спрашивают почти всегда.
Что обычно проверяют:
- Почему в Go только один цикл и как
forзаменяетwhileи бесконечный цикл. - Что
switchне проваливается и зачем тогда нуженfallthrough. - Какую область видимости создаёт init-выражение
if/switch. - Что отдаёт
rangeдля слайса,map, строки и канала и почему опасно брать адрес переменной цикла. - Чем
panic/recoverотличаются от обычной обработки ошибок (ошибки — это значения) и почемуrecoverработает только вdefer.