switch
в Go более общий, чем в C. Выражения не должны быть константами или даже целыми числами, cases оцениваются сверху вниз, пока не будет найдено совпадение, и если switch
не имеет выражения, он включается на true
(то есть как будто бы было указано switch(true){}). Поэтому возможно - и идиоматично - писать if-else-if-else
цепочку как switch
.
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) могут быть представлены в разделенных запятыми списках.
func shouldEscape(c byte) bool {
switch c {
case ' ', '?', '&', '=', '#', '+', '%':
return true
}
return false
}
Хотя они не так распространены в Go, как в других C-подобных языках, операторы break
могут использоваться для раннего завершения switch
. Иногда, однако, необходимо выйти из окружающего цикла (не switch цикла), и в Go это можно сделать, поставив метку в цикле и выходя (breaking) к этой метке. Следующий пример показывает оба варианта использования.
Loop:
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
:
// 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 объявляет переменную в выражении, переменная будет иметь соответствующий тип в каждом условии. Также идиоматично повторно использовать имя в таких случаях, фактически объявляя новую переменную с тем же именем, но с разным типом в каждом случае.
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)
}
Читайте также:
- Эффективный Go: управляющие структуры, оператор if
- Эффективный Go: повторная декларация и переназначение
- Эффективный Go: цикл for
Комментариев нет:
Отправить комментарий