Share This
Связаться со мной
Крути в низ
Categories
//Самоучитель по Go для начинающих. Часть 5. Условные конструкции if-else и switch-case. Цикл for. Вложенные и бесконечные циклы

Самоучитель по Go для начинающих. Часть 5. Условные конструкции if-else и switch-case. Цикл for. Вложенные и бесконечные циклы

samouchitel po go dlja nachinajushhih chast 5 uslovnye konstrukcii if else i switch case cikl for vlozhennye i beskonechnye cikly 1f302fd - Самоучитель по Go для начинающих. Часть 5. Условные конструкции if-else и switch-case. Цикл for. Вложенные и бесконечные циклы

Энтузиаст-разработчик с опытом более трех лет. Сфера интересов — backend, кибербезопасность, web 3.0 В этой части самоучителя мы узнаем про составные части любой программы – условные конструкции и циклы, рассмотрим особенности их реализации в Go, а также решим несколько занимательных задач для закрепления теоретического материала.

samouchitel po go dlja nachinajushhih chast 5 uslovnye konstrukcii if else i switch case cikl for vlozhennye i beskonechnye cikly da68ab1 - Самоучитель по Go для начинающих. Часть 5. Условные конструкции if-else и switch-case. Цикл for. Вложенные и бесконечные циклы

← Часть 4 Переменные. Типы данных и их преобразования. Основные операторы.

Условные конструкции

Условные конструкции предназначены для изменения работы программы в зависимости от заданных условий. Они позволяют управлять потоком выполнения, обрабатывать ошибки и реагировать на различные сценарии.

В Go есть два оператора для создания условных конструкций – if-else и switch-case. Познакомимся с каждым из них подробнее.

Оператор if-else

samouchitel po go dlja nachinajushhih chast 5 uslovnye konstrukcii if else i switch case cikl for vlozhennye i beskonechnye cikly 56911b1 - Самоучитель по Go для начинающих. Часть 5. Условные конструкции if-else и switch-case. Цикл for. Вложенные и бесконечные циклы

Оператор if-else в Go

Оператор if-else в Go имеет стандартный для многих языков программирования синтаксис:

         if условие {   // блок кода в случае истинности условия } else {   // блок кода в случае ложности условия }      

С помощью оператора if-else можно, к примеру, проверить число на чётность:

         num := 12 if num % 2 == 0 { 	fmt.Println("Число чётное") } else { 	fmt.Println("Число нечётное") }      

Эту же конструкцию можно записать в более компактном виде, используя короткое объявление оператора if (if short statement):

         if num := 12; num % 2 == 0 { 	fmt.Println("Число чётное") } else { 	fmt.Println("Число нечётное") }      

Иногда в программе необходимо обработать несколько различных условий. В таких случаях на помощь приходит оператор else if, который проверяет условие в случае ложности предыдущего. Продемонстрируем работу else if на примере программы для определения типа числа, введенного с клавиатуры:

         package main  import ( 	"fmt" )  func main() { 	var num int 	fmt.Scan(&num) // ввод числа 	if num > 0 { 		fmt.Println("Число положительное") 	} else if num < 0 { 		fmt.Println("Число отрицательное") 	} else { 		fmt.Println("Число равно нулю") 	} }      

Буквально конструкцию if-elseif-else можно воспринимать так:

         если условие1 {   блок кода в случае истинности условия1 } иначе если условие2 {   блок кода в случае истинности условия2 } иначе {   блок кода в случае ложности всех предыдущих условий }      

Условия также могут содержать логические операторы, работа которых основана на законах алгебры логики. Для примера приведём код, проверяющий одновременно два чисел на чётность:

         var a, b = 1, 2 if a%2 == 0 && b%2 == 0 { 	fmt.Println("Оба числа чётные") } else if a%2 == 0 || b%2 == 0 { 	fmt.Println("Хотя бы одно число чётное") } else { 	fmt.Println("Оба числа нечётные") }      

Также допускается создание вложенных условий. Но стоит помнить, что высокий уровень вложенности усложняет программу и затрудняет ее понимание.

Например, с помощью вложенных условий можно реализовать простейшую систему аутентификации пользователя:

         var login, pass string fmt.Scan(&login) if login == "Gosha" { 	fmt.Println("Логин верный. Введите пароль.") 	fmt.Scan(&pass) 	if pass == "ilovego" { 		fmt.Println("Пароль верный! Успешный вход!") 	} else { 		fmt.Println("Пароль неверный! Попробуйте еще раз.") 	} } else { 	fmt.Println("Неверный логин") }      

В этом примере мы запрашиваем ввод логина и далее сравниваем введенное значение со строкой "Gosha". В случае соответствия логина выводим сообщение и ожидаем ввод пароля, иначе выводим "Неверный логин". После проверки пароля на равенство строке "ilovego" печатаем сообщение либо об успешном входе, либо о неверном пароле.

👨‍💻 Библиотека Go разработчика Больше полезных материалов вы найдете на нашем телеграм-канале «Библиотека Go разработчика» 🎓 Библиотека Go для собеса Подтянуть свои знания по Go вы можете на нашем телеграм-канале «Библиотека Go для собеса» 🧩 Библиотека задач по Go Интересные задачи по Go для практики можно найти на нашем телеграм-канале «Библиотека задач по Go»

Обработка ошибок

В Go оператор if часто используется для обработки ошибок. Чтобы продемонстрировать это поведение, воспользуемся функцией strconv.Atoi, которая возвращает два значения – результат перевода строки в число и ошибку.

         num, err := strconv.Atoi(“a”) if err != nil {   return err // один из вариантов обработки ошибки }      

Для проверки наличия ошибки используется оператор if, который сравнивает значение переменной err с нулевым (nil). Если err != nil, то это говорит о возникновении ошибки, которую нужно обработать в блоке оператора if.

Switch-case

Оператор switch-case выполняет те же задачи, что и if-else, но позволяет записывать условные выражения в более коротком виде. Он состоит из четырех ключевых слов: switch – для создания оператора, case – для проверки условий (аналог if), default – для задания значения по умолчанию в случае ложности предыдущих условий (аналог else), fallthrough – для принудительного выполнения следующего блока case.

Синтаксис switch-case выглядит следующим образом:

         switch переменная { case значение1: 	// блок кода, если переменная имеет значение1 case значение2: 	// блок кода, если переменная имеет значение2 ... default: 	// блок кода, если переменная не равна ни одному из проверенных значений }      

Пример применения switch-case с указанием переменной для проверки:

         num := 0 switch num { case 0: 	fmt.Println("Число равно нулю") default: 	fmt.Println("Число не равно нулю") }      

Все операторы case выполняются последовательно. Но что если необходимо обязательно учесть определенное условие? В таком случае используется ключевое слово fallthrough. Оно ставится в конце блока case и указывает на то, что следующий оператор case будет выполнен независимо от истинности своего условия.

Пример switch-case без переменной для проверки и с ключевым словом fallthrough:

         num := 3 switch { case num < 5: 	fmt.Println("Число меньше пяти") 	fallthrough // если число меньше 5, то оно точно меньше 10, поэтому здесь можно указать fallthrough case num < 10: 	fmt.Println("Число меньше десяти") 	fallthrough case num < 100: 	fmt.Println("Число меньше ста") default: 	fmt.Println("Число больше пяти") }      

В результате будет выведено:

         Число меньше пяти Число меньше десяти Число меньше ста      

Цикл for

samouchitel po go dlja nachinajushhih chast 5 uslovnye konstrukcii if else i switch case cikl for vlozhennye i beskonechnye cikly c68fff9 - Самоучитель по Go для начинающих. Часть 5. Условные конструкции if-else и switch-case. Цикл for. Вложенные и бесконечные циклы

Цикл for в Go

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

Основным элементом цикла является итератор – переменная, которая по заданному правилу изменяет свое значение.

В отличие от других языков, Go для создания цикла имеет только один оператор for. В общем случае его синтаксис выглядит так:

         for инициализация итератора; условие для итератора; шаг итератора {     // код в цикле }      

В качестве примера посчитаем квадраты чисел от 1 до 9 с использованием цикла:

         for i := 1; i < 10; i++ { 	fmt.Println(i * i) }      

Для достижения необходимого результата бывает полезно изменять параметры цикла. К примеру, отрицательный шаг позволит перебрать значения в обратном порядке, но в таком случае начальное значение должно быть больше конечного:

         // вывод квадратов чисел от 10 до 1 for i := 10; i >= 0; i-- { 	fmt.Println(i * i) }       

Шаг необязательно должен изменяться на единицу. Вместо этого можно использовать любое значение:

         // вывод чётных чисел от 30 до 1 for i := 30; i > 0; i -= 2 { 	fmt.Println(i) }      

Как было упомянуто ранее, циклы часто используются для итерации по массивам. Это реализуется с использованием ключевого слова range, которое задает диапазон перебираемых значений:

         array := []int{10, 20, 30, 40, 50} for index, val := range array { 	fmt.Printf("Элемент с индексом %d: %d\n", index, val) // форматированный вывод }      

Обратите внимание, что первой переменной в таком цикле является индекс, а второй – значение.

При объявлении цикла for необязательно указывать все параметры. Такая особенность была введена неслучайно, ведь это делает возможным реализацию второго типа циклов – while (цикл «пока»). Он выполняется до тех пор, пока заданное условие истинно.

Давайте перепишем предыдущий код для подсчета квадратов чисел от 1 до 9 в стиле цикла while:

         i := 1 for i < 10 { 	fmt.Println(i * i) 	i++ }      

При работе с таким циклом стоит следить за выполнением условия выхода и правильно изменять итератор, иначе есть риск получить бесконечный цикл, способный привести к зависанию или полному краху программы:

         // ошибка: бесконечный цикл for { 	fmt.Println("brrr") }      

Помимо проверки условия есть другой подход для выхода из цикла – оператор break. Он принудительно завершает выполнение цикла. Приведенный ниже код печатает квадраты чисел от 1 до 4 включительно, при этом break обеспечивает досрочный выход из for при достижении итератором числа 5:

         for i := 1; i < 10; i++ { 	if i == 5 { 		break 	} 	fmt.Println(i * i) }       

Несмотря на кажущуюся непригодность, бесконечные циклы бывают полезны для обеспечения бесперебойной работы программы. Чтобы это проиллюстрировать, напишем код для непрерывного считывания данных с консоли до ввода определённого символа:

         for { 	var input string 	fmt.Scan(&input) // ввод данных 	if input == "q" { // условие выхода из цикла 		break 	} }      

Но если есть оператор, останавливающий цикл, то должен быть и продолжающий! И он есть – это оператор continue, досрочно переходящий к следующей итерации. Он бывает полезен для пропуска определенных значений. Например, код ниже выведет на экран квадраты всех чисел от 1 до 20, не делящихся на 3 или 7:

         for i := 1; i <= 20; i++ { 	if i%3 == 0 || i%7 == 0 { 		continue // досрочный переход к следующей итерации цикла 	} 	fmt.Println(i * i) }      

Вложенные циклы

Циклы, как и условные конструкции, могут быть вложенными. Это полезный инструмент для генерации комбинаторных объектов и обработки многомерных структур данных, таких как n-мерные массивы, деревья и графы.

Простым примером вложенного цикла является программа для вывода на экран таблицы умножения чисел от 1 до 10:

         for i := 1; i <= 10; i++ { 	for j := 1; j <= 10; j++ { 		fmt.Print(i*j, "\t") 	} 	fmt.Println() }      

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

Чтобы проиллюстрировать влияние вложенных циклов на производительность, обратимся к примеру с тройным уровнем вложенности, где каждый цикл выполняется n раз, и посчитаем количество итераций:

         n, iterations := 100, 0 for i := 0; i < n; i++ { 	for j := 0; j < n; j++ { 		for k := 0; k < n; k++ { 			iterations++ 		} 	} }  fmt.Println("Количество итераций: ", iterations)      

В примере выше количество операций будет 1003, а в общем случае говорят, что такая программа имеет сложность «порядка n в кубе» или O(n3). На маленьких значениях разница во времени выполнения может быть несущественна, но уже для n = 1000000 программа будет исполнятся критически долго, что недопустимо в условиях реальной разработки. Поэтому стоит избегать необдуманного использования вложенных циклов и оптимизировать их с помощью эффективных алгоритмов.

Для знакомства с понятием сложности алгоритмов рекомендуется прочитать статью Асимптотическая сложность алгоритмов: что за зверь?

Задачи

Пришло время применить изученную теорию на практике. Предлагаем решить несколько несложных задач на условные конструкции и циклы.

Задача 1: Гоша учится считать

samouchitel po go dlja nachinajushhih chast 5 uslovnye konstrukcii if else i switch case cikl for vlozhennye i beskonechnye cikly fc540c5 - Самоучитель по Go для начинающих. Часть 5. Условные конструкции if-else и switch-case. Цикл for. Вложенные и бесконечные циклы

Задача 1: Гоша учится считать

Первокласснику Гоше на уроке математики дали задание: посчитать сумму всех чисел от 20 до 500, которые делятся на 6, и при этом не делятся на 8. Помогите Гоше решить эту задачу.

Решение:

         var sum int for i := 20; i <= 500; i++ { 	if i % 6 == 0 && i % 8 != 0 { 		sum += i 	} } fmt.Println(sum)      

Задача 2: Гоша изобретает калькулятор

samouchitel po go dlja nachinajushhih chast 5 uslovnye konstrukcii if else i switch case cikl for vlozhennye i beskonechnye cikly 4fff290 - Самоучитель по Go для начинающих. Часть 5. Условные конструкции if-else и switch-case. Цикл for. Вложенные и бесконечные циклы

Задача 2: Гоша изобретает калькулятор

Гоша хочет облегчить себе жизнь и создать собственный калькулятор на языке Go, чтобы быстро производить базовые операции над числами.

Входные данные: в первой строке вводятся два целых числа, а на следующей – один из четырех возможных символов, обозначающих математическую операцию: +, -, *, /

Выходные данные: результат применения операции к числам, в случае неверного ввода возвращается сообщение: ««Ошибка, введите два целых числа и одну из четырех допустимых операций: +, -, *, /»

Решение: используем условную конструкцию switch-case

         var a, b int fmt.Scan(&a, &b)  var operation string fmt.Scan(&operation)  switch operation { case "+": 	fmt.Println(a + b) case "-": 	fmt.Println(a - b) case "*": 	fmt.Println(a * b) case "/": 	fmt.Println(a / b) default: 	fmt.Println("Ошибка, введите два целых числа и одну из четырех допустимых операций: +, -, *, /") }      

Задача 3: Гоша учится играть в шахматы

samouchitel po go dlja nachinajushhih chast 5 uslovnye konstrukcii if else i switch case cikl for vlozhennye i beskonechnye cikly 6163166 - Самоучитель по Go для начинающих. Часть 5. Условные конструкции if-else и switch-case. Цикл for. Вложенные и бесконечные циклы

Задача 3: Гоша учится играть в шахматы

Гоша решил сыграть партию в шахматы со своим одноклассником, но забыл, как ходит ладья. Помогите Гоше определить, может ли ладья за один ход попасть с первой клетки на вторую.

Входные данные: четыре числа от 1 до 8 – номер столбца и номер строки сначала для первой клетки, а потом для второй.

Выходные данные: «YES», если из первой клетки можно за один ход попасть во вторую, иначе «NO».

Решение: для проверки условия достаточно сравнить пары координат клеток по вертикали и горизонтали. Если хотя бы одна пара совпадает, то ладья сможет попасть из одной клетки в другую, иначе – нет.

         var x1, y1, x2, y2 int fmt.Scan(&x1, &y1, &x2, &y2) if x1 == x2 || y1 == y2 { 	fmt.Println("YES") } else { 	fmt.Println("NO") }      

Задача 4: Гоша считает делители

samouchitel po go dlja nachinajushhih chast 5 uslovnye konstrukcii if else i switch case cikl for vlozhennye i beskonechnye cikly 19d6f06 - Самоучитель по Go для начинающих. Часть 5. Условные конструкции if-else и switch-case. Цикл for. Вложенные и бесконечные циклы

Задача 4: Гоша считает делители

Гоше стало интересно, как можно найти сумму делителей заданного числа n. Давайте поможем ему решить эту задачу, написав алгоритм на Go.

Входные данные: целое число n.

Выходные данные: сумма делителей числа n.

Решение: достаточно в цикле проверить деление n на все числа от 1 до n / 2, не забыв учесть само число n.

         var n, sum int fmt.Scan(&n) for i := 1; i < n/2+1; i++ { 	if n%i == 0 { 		sum += i 	} } sum += n // учитываем само число fmt.Println(sum)      

Задача 5: Гоша решает задачу со звездочкой

samouchitel po go dlja nachinajushhih chast 5 uslovnye konstrukcii if else i switch case cikl for vlozhennye i beskonechnye cikly ffa1da0 - Самоучитель по Go для начинающих. Часть 5. Условные конструкции if-else и switch-case. Цикл for. Вложенные и бесконечные циклы

Задача 5: Гоша решает задачу со звездочкой

Гоше поручили написать код для детской игры FizzBuzz, правила которой следующие: игроки называют числа подряд, если число делится на 3, его заменяют на «Fizz», если делится на 5, то заменяют на «Buzz», а если делится на 3 и на 5 одновременно, то заменяют на «FizzBuzz». Ваша задача вывести все числа от 1 до 200 по правилам этой игры.

Решение: сразу оговоримся, что у этой задачи есть несколько решений. Самое очевидное заключается в рассмотрении всех возможных случаев, для каждого из которых выводится соответствующая строка. В представленном здесь решении используется похожий подход: каждую итерацию цикла создается строка, к которой приписывается определенное значение, зависящее от делимости итератора на 3 и 5. Если он не делится ни на одно из этих чисел, то к строке припишется строковое значение итератора.

         for i := 1; i <= 200; i++ { 	var s string // заново инициализируем пустую строку 	if i%3 == 0 {  		s += "Fizz" 	} 	if i%5 == 0 { 		s += "Buzz" 	} 	if s == "" { // если текущее число не делится на 3 и на 5 		s += fmt.Sprint(i) // записываем в строку текущее число 	} 	fmt.Println(s) // выводим строку }      

Подведём итоги

В этой части самоучителя по Go мы познакомились с фундаментальными понятиями в программировании – условными конструкциями и циклами. Их понимание позволит в дальнейшем создавать гибкие и функциональные программы.

В следующем уроке рассмотрим функции, аргументы, рекурсию и defer, а в конце по традиции закрепим теорию интересными задачами.

***

Содержание самоучителя

  1. Особенности и сфера применения Go, установка, настройка
  2. Ресурсы для изучения Go с нуля
  3. Организация кода. Пакеты, импорты, модули. Ввод-вывод текста.
  4. Переменные. Типы данных и их преобразования. Основные операторы
  5. Условные конструкции if-else и switch-case. Цикл for. Вложенные и бесконечные циклы.

  • 0 views
  • 0 Comment

Leave a Reply

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.

Связаться со мной
Close