Циклы
Бесконечный
1 2 3 4 |
for { ... } // выход из цикла делается при помощи break |
Цикл пока условие выполняется:
1 2 3 |
for условие { ... } |
Классический цикл со счётчиком:
1 2 3 |
for i := 0; i < x; i++ { ... } |
Цикл по элементам (массива, среза, мапы, по рунам в строке…):
1 2 3 4 5 6 |
for key, val := range myMap for key := range myMap for idx, val := range mySlice for idx, val := range myString for idx := range myString for val := range myChannel |
Прерывание цикла — break, переход к следующей итерации — continue.
Условия
1 2 3 4 5 6 7 |
if условие { ... } else if условие { ... } else { ... } |
Условие должно быть выражением типа bool. Это вместе с «несовместимостью» типов означает, что нельзя сделать так
1 2 3 4 |
x := 1 if x { ... } |
x — целое, а не логическое. Потому надо писать полное условие вроде x != 0.
Естественно, else-часть является не обязательной. Ну и не забываем о небольших «хитростях», делающих код короче. Вроде этой
1 2 3 |
if val, found := myMap[key]; found { ... } |
Ветвление
Есть три варианта switch:
- классический
- на условиях (альтернатива куче if’ов)
- по типу
Классический:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var name string ... switch name { case "Вася", "Петя": if name == "Петя" { println(333) break // выход из switch } println(1111) case "Миша": println(22) default: println(444444) } |
Использовать break в конце каждого блока не нужно — автоперехода в следующий блок не происходит (в отличие от С, Java, PHP и т.п.). Если нам всё же нужно перейти в следующий блок, то в конце покидаемого блока ставим fallthrough.
Если наш switch находится внутри цикла и выйти надо из цикла (прервать его), делается это через метку:
1 2 3 4 5 6 7 8 |
Loop: // имя метки, можно задавать как нравится for key, val := range myMap { switch { case key == "Имя" && val == "Вася": println("bla-bla-bla") break Loop } } |
На условиях:
1 2 3 4 5 6 7 8 |
switch { case name == "Вася": ... case x > 20: ... default: ... } |
Надо не забывать две вещи. Во-первых, это частный случай классического свитча. В качестве выражения выступает неявное указание true, как если бы мы явно указали switch true. Во-вторых, сработает первый кейс, условие которого выдаст true. То есть, если в примере выше х больше 20 и имя «Вася», то сработает кейс только для имени.
По типу:
1 2 3 4 5 6 7 8 |
switch zVar.(type) { case nil: ... case int: ... case []byte, []rune, string: ... } |
Такое ветвление считается нежелательным и надо стараться использовать его только там, где это необходимо. В прочих случаях стараемся обходиться ООП с go-шной утиной типизацией.
default-часть в свитчах не является обязательной и может находиться не только в конце блока, но и в начале.