Зайди на русскоязычный сайт golangs.org. В серии уроков по Golang ты найдёшь урок, который называется - Цикл for, if-else-switch, True-False и операторы сравнения в Golang. В нём помимо свич есть также все основные знания логики.
switch в Go более общий, чем в C. Выражения не должны быть константами или даже целыми числами, cases оцениваются сверху вниз, пока не будет найдено совпадение, и если switch не имеет выражения, он включается на true (то есть как будто бы было указано switch(true){}). Поэтому возможно - и идиоматично - писать if-else-if-else цепочку как switch.
1 2 3 4 5 6 7 8 9 10 11 |
func unhex(c byte) byte { switch { case '0' <= c && c <= '9': return c - '0' case 'a' <= c && c <= 'f': return c - 'a' + 10 case 'A' <= c && c <= 'F': return c - 'A' + 10 } return 0 } |
Нет автоматического провала (то есть случая использования нескольких case одновременно для объединения их в один результат), но случаи (cases) могут быть представлены в разделенных запятыми списках.
1 2 3 4 5 6 7 |
func shouldEscape(c byte) bool { switch c { case ' ', '?', '&', '=', '#', '+', '%': return true } return false } |
Хотя они не так распространены в Go, как в других C-подобных языках, операторы break могут использоваться для раннего завершения switch. Иногда, однако, необходимо выйти из окружающего цикла (не switch цикла), и в Go это можно сделать, поставив метку в цикле и выходя (breaking) к этой метке. Следующий пример показывает оба варианта использования.
Loop:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
for n := 0; n < len(src); n += size { switch { case src[n] < sizeOne: if validateOnly { break } size = 1 update(src[n]) case src[n] < sizeTwo: if n+1 >= len(src) { err = errShortInput break Loop } if validateOnly { break } size = 2 update(src[n] + src[n+1]<<shift) } } |
Конечно, оператор continue также принимает необязательную метку, но это относится только к циклам.
Вот процедура сравнения для байтовых срезов, которая использует два оператора switch:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
// Compare возвращает число сравнивая два байтовых среза, // лексикографически. // Результат будет 0 если a == b, -1 если a < b, // и +1 если a > b func Compare(a, b []byte) int { for i := 0; i < len(a) && i < len(b); i++ { switch { case a[i] > b[i]: return 1 case a[i] < b[i]: return -1 } } switch { case len(a) > len(b): return 1 case len(a) < len(b): return -1 } return 0 } |
Переключатель типов (Type switch)
switch также может быть использован для обнаружения динамического типа переменной интерфейса. Такой type switch использует синтаксис утверждения типа (type assertion) с ключевым словом type в круглых скобках. Если switch объявляет переменную в выражении, переменная будет иметь соответствующий тип в каждом условии. Также идиоматично повторно использовать имя в таких случаях, фактически объявляя новую переменную с тем же именем, но с разным типом в каждом случае.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
var t interface{} t = functionOfSomeType() switch t := t.(type) { default: // %T печатает type, который t имеет fmt.Printf("неожидаемый тип %T\n", t) case bool: // t имеет type bool fmt.Printf("boolean %t\n", t) case int: // t имеет type int fmt.Printf("integer %d\n", t) case *bool: // t имеет type *bool fmt.Printf("pointer к boolean %t\n", *t) case *int: // t имеет type *int fmt.Printf("pointer к integer %d\n", *t) } |
Спасибо большое, ребят, за то, что смогли мне наконец-таки объяснить это. Теперь всё стало намного понятнее. Буду теперь нарешивать задачки с использованием свичей.