Урок 4. Условия, switch и цикл for
В других языках есть while, do … while, тернарный оператор ?:. В Go всё проще: условия — if и switch, цикл — только for, но в нескольких формах.
if и else
package main
import "fmt"
func main() {
score := 74
if score >= 90 {
fmt.Println("отлично")
} else if score >= 70 {
fmt.Println("хорошо")
} else {
fmt.Println("нужно подтянуть")
}
}хорошоУсловия проверяются сверху вниз, выполняется только первый подошедший блок. Правила записи:
- условие пишут без скобок:
if score >= 90, а неif (score >= 90)(скобки допустимы, ноgo fmtих уберёт); - фигурные скобки обязательны, даже если внутри одна строка;
elseстоит на той же строке, что закрывающая}предыдущего блока, — иначе ошибка компиляции.
Сравнения: ==, !=, <, <=, >, >=. Логические операции: && (и), || (или), ! (не). Условие должно быть именно bool: if n для числа n не соберётся, нужно if n != 0.
Тернарного оператора условие ? a : b в Go нет — пишут обычный if.
if с коротким объявлением
Перед условием можно объявить переменную — она будет видна только внутри if и его else:
package main
import "fmt"
func main() {
price, discount := 120, 15
if total := price - discount; total > 100 {
fmt.Println("бесплатная доставка, сумма", total)
} else {
fmt.Println("доставка платная, сумма", total)
}
}бесплатная доставка, сумма 105Чаще всего так проверяют ошибки: if err := сделать(); err != nil { … } — об этом в уроке Функции и ошибки.
switch
switch сравнивает значение с вариантами по порядку. В отличие от C и Java, break в конце варианта не нужен: выполняется только один case.
package main
import "fmt"
func main() {
day := "сб"
switch day {
case "пн", "вт", "ср", "чт", "пт":
fmt.Println("рабочий день")
case "сб", "вс":
fmt.Println("выходной")
default:
fmt.Println("нет такого дня")
}
t := 15
switch {
case t < 0:
fmt.Println("мороз")
case t < 20:
fmt.Println("прохладно")
default:
fmt.Println("тепло")
}
}выходной
прохладно- В одном
caseможно перечислить несколько значений через запятую. defaultвыполняется, если не подошёл ни один вариант.switchбез значения — это цепочка условий: срабатывает первыйcase, условие которого истинно. Так длинныеif … else ifчитаются легче.
Если нужно, чтобы после варианта выполнился и следующий, пишут fallthrough — нужно это редко:
package main
import "fmt"
func main() {
switch n := 1; n {
case 1:
fmt.Println("один")
fallthrough
case 2:
fmt.Println("два")
case 3:
fmt.Println("три")
}
}один
дваfallthrough переходит в следующий case, не проверяя его условие, и только на один шаг: до "три" дело не дошло.
Цикл for
Классическая форма — три части через точку с запятой: начало, условие, шаг:
package main
import "fmt"
func main() {
sum := 0
for i := 1; i <= 5; i++ {
sum += i
}
fmt.Println("сумма от 1 до 5:", sum)
}сумма от 1 до 5: 15Переменная i видна только внутри цикла. Скобок вокруг трёх частей нет, фигурные скобки обязательны.
for вместо while
Если оставить одно условие, получится цикл «пока» — как while в других языках:
package main
import "fmt"
func main() {
n := 2024
digits := 0
for n > 0 {
digits += n % 10
n /= 10
}
fmt.Println("сумма цифр:", digits)
}сумма цифр: 8n % 10 — последняя цифра числа, n /= 10 отбрасывает её. Цикл идёт, пока цифры не кончатся.
Без условия совсем — бесконечный цикл for { … }. Из него выходят командой break или return.
break и continue
break прерывает цикл, continue пропускает остаток текущего шага и переходит к следующему:
package main
import "fmt"
func main() {
for i := 1; ; i++ {
if i%2 == 0 {
continue
}
if i > 7 {
break
}
fmt.Println(i)
}
}1
3
5
7Здесь у цикла нет условия (между точками с запятой пусто), поэтому он закончится только на break.
Во вложенных циклах break выходит только из внутреннего. Чтобы выйти сразу из обоих, у внешнего цикла ставят метку:
package main
import "fmt"
func main() {
outer:
for i := 1; i <= 3; i++ {
for j := 1; j <= 3; j++ {
if i*j == 4 {
break outer
}
fmt.Println(i, j)
}
}
fmt.Println("готово")
}1 1
1 2
1 3
2 1
готовоКак только i*j стало равно 4 (при i = 2, j = 2), оба цикла закончились. continue outer так же переходит к следующему шагу внешнего цикла.
for range
range перебирает элементы: числа от нуля, буквы строки, элементы срезов и map. С Go 1.22 можно перебирать и просто число:
package main
import "fmt"
func main() {
for i := range 3 {
fmt.Println("повтор", i)
}
for i, r := range "Го!" {
fmt.Println(i, string(r))
}
}повтор 0
повтор 1
повтор 2
0 Г
2 о
4 !range 3 даёт 0, 1, 2. У строки range выдаёт пару: номер байта, с которого начинается символ, и сам символ (rune). Русская буква занимает два байта, поэтому номера идут 0, 2, 4. Срезы и map перебираются так же — это в следующих уроках.
Частые ошибки
elseна новой строке после}— ошибка компиляцииsyntax error, в которой упомянутelse. Пишите} else {в одну строку.if x = 5вместоif x == 5— не соберётся: в условии нужно сравнение.- Цикл
for i := 0; i <= len(s); i++— лишний шаг и выход за границы среза. Для индексов —<, а лучшеrange. - Ожидание, что
switch«проваливается» в следующийcase, как в C, — в Go так не бывает безfallthrough.
Коротко
if условие { … } else { … }— без скобок вокруг условия, с обязательными{ }.if x := …; условие— переменная только для этогоif.switchне требуетbreak; несколько значений — через запятую;switchбез значения заменяет цепочкуif.- Цикл один —
for:for i := 0; i < n; i++,for условие,for { },for i := range n. breakиcontinue; метка — чтобы выйти из внешнего цикла.