if, switch и логика решений

В Go условные конструкции простые, но имеют свои особенности. Давайте разберемся без паники.

Конструкция if

Базовый синтаксис

age := 18

if age >= 18 {
    fmt.Println("Можно голосовать")
} else {
    fmt.Println("Еще рано")
}
В Go фигурные скобки обязательны, даже для одной строки кода. Круглые скобки вокруг условия не нужны.

if с инициализацией

Уникальная фишка Go - можно объявить переменную прямо в if:

if err := doSomething(); err != nil {
    // err видна только здесь
    return err
}
// err здесь уже не существует

Цепочки условий

score := 85

if score >= 90 {
    fmt.Println("Отлично!")
} else if score >= 80 {
    fmt.Println("Хорошо")
} else if score >= 70 {
    fmt.Println("Удовлетворительно")
} else {
    fmt.Println("Нужно подучить")
}

Switch - мощная альтернатива

Базовый switch

day := "понедельник"

switch day {
case "понедельник":
    fmt.Println("Начало недели")
case "пятница":
    fmt.Println("TGIF!")
case "суббота", "воскресенье":
    fmt.Println("Выходные!")
default:
    fmt.Println("Будний день")
}
В Go не нужен break в конце case. Выполнение не проваливается в следующий case автоматически.

Switch без выражения

Можно использовать switch как замену длинным if-else:

score := 85

switch {
case score >= 90:
    fmt.Println("A")
case score >= 80:
    fmt.Println("B")
case score >= 70:
    fmt.Println("C")
default:
    fmt.Println("F")
}

Switch с инициализацией

import (
    "fmt"
    "runtime"
)

switch os := runtime.GOOS; os {
case "darwin":
    fmt.Println("macOS")
case "linux":
    fmt.Println("Linux")
default:
    fmt.Printf("Другая ОС: %s\n", os)
}

Сравнение операторов

<ComparisonTable data={{ headers: ["Оператор", "Описание", "Пример"], rows: [ ["==", "Равно", "x == y"], ["!=", "Не равно", "x != y"], [">", "Больше", "x > y"], ["<", "Меньше", "x < y"], [">=", "Больше или равно", "x >= y"], ["<=", "Меньше или равно", "x <= y"], ["&&", "Логическое И", "x && y"], ["||", "Логическое ИЛИ", "x || y"], ["!", "Логическое НЕ", "!x"] ] }} />

Type switch

Особый вид switch для проверки типов. Использует интерфейсы - мы разберём их подробно в уроке про интерфейсы. Пока просто посмотри на синтаксис:

func describe(i interface{}) {
    switch v := i.(type) {
    case int:
        fmt.Printf("Целое число: %d\n", v)
    case string:
        fmt.Printf("Строка: %s\n", v)
    case bool:
        fmt.Printf("Булево: %t\n", v)
    default:
        fmt.Printf("Неизвестный тип: %T\n", v)
    }
}

Практический пример

package main

import "fmt"

func checkPassword(password string) string {
    switch {
    case len(password) < 8:
        return "Слишком короткий (нужно минимум 8 символов)"
    case len(password) > 32:
        return "Слишком длинный (максимум 32 символа)"
    default:
        return "Длина подходит - проверь цифры и заглавные буквы вручную"
    }
}

func main() {
    fmt.Println(checkPassword("123"))          // Слишком короткий
    fmt.Println(checkPassword("password123"))  // Длина подходит
    fmt.Println(checkPassword("слишкомДлинныйПарольКоторыйТочноНеЗапомнится")) // Слишком длинный
}

Лучшие практики

1. Используйте switch вместо длинных if-else

// Плохо
if x == 1 {
    // ...
} else if x == 2 {
    // ...
} else if x == 3 {
    // ...
}

// Хорошо
switch x {
case 1:
    // ...
case 2:
    // ...
case 3:
    // ...
}

2. Группируйте связанные условия

switch day {
case "суббота", "воскресенье":
    fmt.Println("Выходной")
case "понедельник", "вторник", "среда", "четверг", "пятница":
    fmt.Println("Рабочий день")
}

3. Используйте ранний возврат

import "errors"

func process(data string) error {
    if data == "" {
        return errors.New("пустые данные")
    }

    if len(data) > 1000 {
        return errors.New("слишком большие данные")
    }

    // Основная логика
    return nil
}

Частые ошибки

1. Забыть фигурные скобки (обязательны в Go) 2. Использовать круглые скобки вокруг условия (не нужны) 3. Ожидать проваливания в switch (нужен fallthrough) 4. Сравнивать с nil неправильно

Итоги

  • if в Go требует фигурных скобок, круглые - не нужны
  • switch не требует break - выход автоматический
  • Можно инициализировать переменную прямо в if и switch
  • Type switch - для проверки типа интерфейсного значения (подробнее в уроке про интерфейсы)

В следующем уроке разберём циклы - в Go есть только for, но он умеет всё!

Типичная ошибка

Ожидать проваливания в следующий case как в C или PHP. В Go этого не происходит - нужен явный fallthrough.

Зарегистрируйтесь бесплатно, чтобы пройти квиз, решить задание с автопроверкой и вести прогресс.