Skip to content

Блоки потока управления: switch-case

switch-case блок потока управления является одним из видов блоков потока управления условным выполнением.

Полная форма switch-case блока.

В полной форме:

  • switch, case и default — три ключевых слова.

  • Часть InitSimpleStatement должна быть простым утверждением. Часть CompareOperand0 представляет собой выражение, которое рассматривается как типизированное значение (если это нетипизированное значение, то оно рассматривается как значение типа своего типа по умолчанию), поэтому оно не может быть нетипизированным nil. CompareOperand0 называется выражением переключения в спецификации Go.

  • Каждая из частей CompareOperandListX ( X может представлять от 1 до N) должна быть списком выражений, разделенных запятыми. Каждое из этих выражений должно быть сравнимо с CompareOperand0. Каждое из этих выражений называется выражением case в спецификации Go. Если выражение case является нетипизированным значением, оно должно быть неявно преобразовано в тип выражения switch в том же switch-case потоке управления. Если преобразование невозможно, компиляция завершается ошибкой.

Каждый case CompareOperandListX: или default: открывает (и за ним следует) неявный блок кода. Неявный блок кода и тот case CompareOperandListX: или default: образуют ветвь. Каждая такая ветвь не является обязательной. Позже мы назовем блок неявного кода в такой ветви блоком кода ветви.

В блоке потока управления может быть не более одной default ветви switch-case.

Помимо блоков кода ответвления, каждый switch-case поток управления формирует два блока кода: один неявный и один явный. Явный вложен в неявный. Все блоки кода ветвления вложены в явный и косвенно вложены в неявный.

switch-case блоки потока управления являются разрушаемыми, поэтому break операторы также могут использоваться в любом блоке кода ответвления в блоке потока управления, чтобы заранее switch-case выполнить переход из блока потока управления switch-case.

Блок InitSimpleStatement в цикле for будет выполнен (только один раз) перед выполнением других операторов в for блоке цикла.

Сначала InitSimpleStatement будет выполнено, когда будет выполнен switch-case поток управления, затем выражение переключения CompareOperand0 будет оцениваться только один раз. Результат оценки всегда является типизированным значением. Результат оценки будет сравниваться при помощи \== оператора с результатом оценки каждого выражения case в CompareOperandListX списках выражений сверху вниз и слева направо. Если обнаруживается, что выражение case равно CompareOperand0, процесс сравнения останавливается и выполняется соответствующий блок кода ответвления выражения. Если ни одно из выражений case не окажется равным CompareOperand0, будет выполнен блок кода ответвления по умолчанию, если он присутствует.

Пример switch-case потока управления:

Функция rand.Intn возвращает неотрицательное int случайное значение, которое меньше указанного аргумента.

Обрати внимание: если любые два выражения case в switch-case потоке управления могут быть обнаружены как равные во время компиляции, то компилятор может отклонить последнее. Например, стандартный компилятор Go считает case 6, 7, 8 строку в приведенном выше примере недопустимой, если она не закомментирована. Но другие компиляторы могут подумать, что эта строка подходит. На самом деле, текущий стандартный компилятор Go (версия 1.19) допускает дублирование выражений регистра логических значений, а gccgo (v8.2) допускает дублирование выражений регистра логических и строковых значений.

Подробнее о дублировании выражений регистра логических значений ты можешь узнать на сайте GitHub.

Как видно из комментариев в приведенном выше примере, в отличие от многих других языков, в Go в конце каждого блока кода ветвления выполнение автоматически выходит за пределы соответствующего switch-case блока управления. Тогда как позволить выполнению перейти к следующему блоку кода ветвления? Go предоставляет ключевое слово fallthrough  для выполнения этой задачи. Например, в следующем примере каждый блок кода ответвления будет выполняться в соответствии с их порядком сверху вниз.

Пожалуйста, обрати внимание:

  • Оператор fallthrough должен быть последним оператором в ветке.

  • Оператор fallthrough не может отображаться в последней ветви в блоке потока управления switch-case.

Например, все следующие fallthrough виды использования являются незаконными.

Части InitSimpleStatement и CompareOperand0 в switch-case потоке управления являются необязательными. Если CompareOperand0 часть отсутствует, она будет рассматриваться как true типизированное значение встроенного типа bool. Если InitSimpleStatement часть отсутствует, точка с запятой после нее может быть опущена.

И, как упоминалось выше, все ветки необязательны. Таким образом, все следующие блоки кода являются допустимыми, все они могут рассматриваться как недействующие.

Для последних двух switch-case блоков потока управления в последнем примере, как упоминалось выше, каждая из отсутствующих CompareOperand0 частей рассматривается как типизированное значение true встроенного типа bool. Таким образом, следующий фрагмент кода напечатает hello.

Другим очевидным отличием от многих других языков является то, что порядок default ветвления в switch-case блоке потока управления может быть произвольным. Например, следующие три switch-case блока потока управления эквивалентны друг другу.