if, switch и логика решений
В Go условные конструкции простые, но имеют свои особенности. Давайте разберемся без паники.
Конструкция if
Базовый синтаксис
age := 18
if age >= 18 {
fmt.Println("Можно голосовать")
} else {
fmt.Println("Еще рано")
}
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("Будний день")
}
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
}
Частые ошибки
Итоги
ifв Go требует фигурных скобок, круглые - не нужныswitchне требуетbreak- выход автоматический- Можно инициализировать переменную прямо в
ifиswitch - Type switch - для проверки типа интерфейсного значения (подробнее в уроке про интерфейсы)
В следующем уроке разберём циклы - в Go есть только for, но он умеет всё!
Типичная ошибка
Ожидать проваливания в следующий case как в C или PHP. В Go этого не происходит - нужен явный fallthrough.