Go — Условия и циклы


Введение

Добро пожаловать в четвертую часть цикла лекций по Go lang. В части 3 мы рассмотрели указатели и пользовательский ввод. Посмотрите ее: https://dev.to/vchiranjeeviak/go-pointers-user-input-4mh9, если вы ее пропустили. В этой части мы рассмотрим условия и циклы в Go.

Условия

В целом, программирование — это написание логики в виде кода так, чтобы машина могла его понять. Одной из самых важных частей написания логики является работа с некоторыми условиями. Мы можем захотеть, чтобы наша машина реагировала по-разному в различных ситуациях. В таких случаях мы задаем эти ситуации в виде условий и пишем, как машина должна работать в этих ситуациях. Мы делаем это с помощью условий.

Мы можем написать условия двумя способами. Это:

  1. if-else.
  2. switch-case.

1. if-else

  • Код, который мы хотим выполнить при выполнении определенного условия, записывается внутри блока if вместе с условием.
  • Код, который мы хотим выполнить, если условие не выполняется, записывается в блоке else.

Синтаксис для использования if-else следующий:

if <condition> {
    // code which needs to be executed if above condition is met
} else {
    // code which needs to be executed when above condition is not met
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Условие

Условие в синтаксисе if-else может быть любой комбинацией логических операций и реляционных операций.

В Go lang существует множество типов операторов, и логические и реляционные операторы — два из них.

Прежде чем перейти к ним, необходимо кое-что узнать об операндах. Операнд — это переменная или значение, над которым оператор выполняет операцию.

Логические операторы

Операция, выполняемая с помощью логических операторов, называется логической операцией. Существует 3 логических оператора. Это AND (&&), OR (||) и NOT (!). Эти логические операторы применяются к операндам, которые могут быть оценены в булево значение (true или false). AND и OR являются бинарными операторами (см. часть 3) и принимают два операнда по обе стороны от оператора. AND вычисляет истину только тогда, когда оба операнда истинны или ложны в любом другом случае. OR оценивает истинность, когда хотя бы один из них истинен или ложен в любом другом случае.

операнд 1 оператор операнд 2 результат
Истинно И Истинно True
True И Ложь Ложь
Ложь И Истинно Ложь
Ложь И Ложь Ложь
True ИЛИ Истинно Истинно
Истинно ИЛИ Ложь Правда
Ложь ИЛИ Истинно Истинно
Ложь ИЛИ Ложь Ложь

NOT принимает только одно из булевых значений и возвращает другое.

Оператор Операнд Результат
НЕ Истина Ложь
НЕ Ложь Верно

Okay…. Это хорошо, но откуда мы возьмем эти True или False?

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

Реляционные операторы

Реляционные операторы — это операторы, которые проверяют, истинна или нет заданная связь между двумя операндами. Скажем, если есть выражение «5 больше 6», то оно задает отношение между двумя операндами и в этом случае очевидно ложно.

Существует 6 реляционных операторов. Это:

Операнд 1 Оператор Операнд 2 Результат
5 == (равно) 6 Ложь
5 != (не равно) 6 Истинно
5 > (больше чем) 6 Ложь
5 >= (больше, чем или равно) 6 Ложь
5 < (меньше чем) 6 Правда
5 <= (меньше или равно) 6 True

Программа для иллюстрации if-else

Мы пишем программу для проверки того, находится ли заданное пользователем целое число в диапазоне [0, 100]. В зависимости от входных данных мы будем печатать уникальное сообщение. В этом сообщении говорится, что число должно находиться в диапазоне от 0 до 100, и может быть равно 0, но не равно 100. Одно из наших реляционных выражений должно быть наше число >= 0, а другое — наше число < 100. И нам нужно объединить оба выражения с помощью AND (&&), потому что оба они являются необходимыми проверками.

package main

import "fmt"

func main() {

    var someNumber int

    fmt.Println("Enter an integer:")

    fmt.Scan(&someNumber)

    if ((someNumber >= 0) && (someNumber < 100)) { // Condition
        fmt.Println("In our range") // Comes here only when the condition is true
    } else {
        fmt.Println("Not in our range") // Comes here only when the condition is false
    }
} 
Вход в полноэкранный режим Выйти из полноэкранного режима

2. переключатель-случай

Я не хочу усложнять switch-case, потому что он так же прост, как и настоящая коммутационная панель. Мы можем спроектировать цифровую плату выключателя точно так же, как мы имеем уникальный выключатель для вентилятора, света, лампочки и т.д..

Синтаксис для switch-case:

switch (<variable/value>) {
    case <some value>:
        // code
    case <some other value>:
        // code
    default:
        // code
}
Войти в полноэкранный режим Выход из полноэкранного режима

Программа для иллюстрации switch-case

Этого примера достаточно, чтобы понять принцип работы switch-case. Мы принимаем от пользователя строку. Если в качестве входных данных задано «вентилятор», мы выводим «включил вентилятор». Если в качестве входных данных указано «свет», мы выводим «включил свет». Если это что-то другое, мы выводим «Нажмите нужный выключатель».

package main

import "fmt"

func main() {

    var userInput string

    fmt.Println("Give input:")
    fmt.Scan(&userInput)

    switch (userInput) {
        case "fan":
            fmt.Println("switched fan on")
        case "light":
            fmt.Println("switched light on")
        default:
            fmt.Println("Press the correct switch")
    }
}
Вход в полноэкранный режим Выход из полноэкранного режима

Примечание: В этой статье я не привожу выводов. Пожалуйста, проверьте сами и прокомментируйте, если найдете ошибки в коде.

  • Мы можем написать тот же код, используя if-else. Попробуйте сделать это самостоятельно и прокомментируйте, если у вас возникнут трудности. Я знаю, что это базовые вещи, если вы знакомы с другими языками программирования, но это может быть сложным для тех, кто только начал программировать.

Циклы

Бывают ситуации, когда мы хотим выполнить некоторый блок кода несколько раз. При этом количество повторений может определяться условием или событием. Примером может быть ситуация «Принимать строку от пользователя, пока она не станет специальной» или «Выводить числа от 1 до 100» и т.д. Везде, где мы видим повторение задачи, мы можем применить циклы.

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

for <condition> {
    // repetitive task
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Пока условие не будет выполнено (оценено в True), код, записанный внутри цикла, будет выполняться снова и снова.

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

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

Давайте объявим переменную для хранения входных данных и напишем оператор Scan внутри цикла for. Но нам нужно придумать условие, которое удовлетворит нашу ситуацию. Нам нужно остановить цикл только тогда, когда мы получим special. Таким образом, нам нужно заставить его работать до тех пор, пока на вход не придет special. И еще выведем строку после цикла, чтобы показать, что управление программой вышло из него.

package main

import "fmt"

func main() {
    var userInput string

    for userInput != "special" {
        fmt.Scan(&userInput)
    }
    fmt.Print("Outside loop")
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Программа будет работать до тех пор, пока вы не введете special.

Программа для печати чисел в диапазоне [1, 100)

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

package main

import "fmt"

func main(){
    number := 1
    for number <= 99 {
        fmt.Println(number)
        number++
    }
}
Вход в полноэкранный режим Выход из полноэкранного режима

++ — это унарный оператор, который увеличивает значение переменной на 1.

  • Каждый раз, когда мы заходим в цикл, мы называем это итерацией. Это важная терминология, которую необходимо знать для следующих тем.

Мы инициализируем переменную вне цикла, записываем на нее условие и обновляем ее значение внутри цикла, просто печатая ее значение в цикле. Если код в файле огромен, отслеживание этой конкретной переменной может стать трудной задачей. Поэтому лучше обрабатывать такие переменные внутри параметров for. Синтаксис следующий:

for (<initialisation>; <condition>; <updation>) {
    //code
} 
Войти в полноэкранный режим Выйти из полноэкранного режима

Давайте посмотрим, как приведенный выше код может быть преобразован в этот метод.

package main

import "fmt"

func main() {
    for (number := 1; number <= 99; number++) {
        fmt.Println(number)
    }
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Это может быть гораздо более читабельным и чистым.

Бесконечные циклы

Бесконечный цикл — это цикл, который не останавливается и выполняется вечно либо до тех пор, пока не закончится память, либо пока не отключится питание. Большинство современных языков программирования и их среды времени выполнения или компиляторы аккуратно справляются с этим, не позволяя вашей системе зависнуть. Да, именно это и происходит, когда ваша оперативная память заполнена приложениями. Как мы можем вызвать бесконечный цикл? Это очень просто сделать. Нужно просто задать условие (проверьте синтаксис цикла) в цикле, которое никогда не станет ложным. Одним из таких условий может быть 0 > 10. Это условие всегда будет ложным, как бы ни менялись переменные в программе. Или мы можем просто дать true (boolean) в качестве условия, так как в любом случае любое условие, которое мы даем в конце, оценивается либо в true, либо в false.

Программа для печати 1 бесконечное количество раз

package main

import "fmt"

func main() {
    for true {
        fmt.Println(1)
    }
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Это может дать предупреждение о том, что true не обязательно предоставлять, так как если мы ничего не предоставляем, то программа считает это как true.
Таким образом, исправленная идеальная программа может быть такой:

package main

import "fmt"

func main() {
    for {
        fmt.Println(1)
    }
}
Войти в полноэкранный режим Выход из полноэкранного режима

Я призываю вас запустить это и посмотреть, как печатается бесконечный цикл, если вы новичок. Если вы не новичок, я уверен, что вы видели это много раз.

  • Если бы мы дали false вместо true, цикл не выполнился бы ни разу.

Можно ли запускать конечные циклы, не задавая условия? Ответ частично положительный. Потому что мы все равно задаем условие, но не в том месте, где обычно задаем. Мы задаем условие, когда нужно прекратить выполнение внутри цикла, но не вне его. Для этого мы используем break и continue.

Break и Continue

break и continue — это два ключевых слова в большинстве языков программирования, так же как и в Go. Когда цикл запущен, если мы хотим остановить его выполнение на определенной итерации и не запускать дальше, мы используем break. Когда цикл запущен, если мы хотим пропустить одну конкретную итерацию и выполнить оставшиеся итерации нормально, мы используем continue.

Программа для печати [1, 100) с использованием break

package main

import "fmt"

func main(){
    number := 1
    for {
        if (number == 100) {
            break
        }
        fmt.Println(number)
        number++
    }
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Эта программа также печатает 1, 99. Но разница в том, как мы написали цикл и базовое условие.

Программа для печати [1, 100), но не печатайте 10

package main

import "fmt"

func main(){
    number := 1
    for {
        if (number == 10) {
            continue
        }
        if (number == 100) {
            break
        }
        fmt.Println(number)
        number++
    }
}
Вход в полноэкранный режим Выйти из полноэкранного режима
  • Если вы думаете, что здесь будут печататься от 1 до 99, то вы ошибаетесь. Почему? Потому что, когда число равно 10, оно переходит в блок if и выполняет continue, что выводит его непосредственно из цикла и возвращает в цикл сверху. Он никогда не выполнит строку number++, что означает, что значение числа не сдвинется с 10 и будет продолжать вращаться в цикле, что делает его бесконечным.

Чтобы заставить его работать так, как мы задумали, нам нужно внести небольшое изменение:

package main

import "fmt"

func main(){
    number := 1
    for {
        if (number == 10) {
            continue
            number++ // new added line
        }
        if (number == 100) {
            break
        }
        fmt.Println(number)
        number++
    }
}
Войти в полноэкранный режим Выйти из полноэкранного режима
  • Эта добавленная строка гарантирует, что значение числа будет увеличиваться, даже когда оно попадает в continue.

Заключение

На этом все… Ставьте лайк и делитесь информацией, если она вам понравилась. Следите за моими будущими материалами.

Давайте общаться: Twitter LinkedIn Showwcase

Оцените статью
devanswers.ru
Добавить комментарий