Ответ 1
Да. Он называется переключателем Type. Он позволяет выполнять код в зависимости от фактического типа интерфейса, который вы передаете.
Я думаю, официальная документация, с ее примером, понятна:
Переключатель также может использоваться для обнаружения динамического типа интерфейса переменная. Такой коммутатор типа использует синтаксис утверждения типа с тип ключевого слова внутри круглых скобок. Если переключатель объявляет переменная в выражении, переменная будет иметь соответствующую введите в каждом пункте. Это также идиоматично для повторного использования имени в таких случаев, в действительности объявляющих новую переменную с тем же именем, но различного типа в каждом случае.
var t interface{}
t = functionOfSomeType()
switch t := t.(type) {
default:
fmt.Printf("unexpected type %T", t) // %T prints whatever type t has
case bool:
fmt.Printf("boolean %t\n", t) // t has type bool
case int:
fmt.Printf("integer %d\n", t) // t has type int
case *bool:
fmt.Printf("pointer to boolean %t\n", *t) // t has type *bool
case *int:
fmt.Printf("pointer to integer %d\n", *t) // t has type *int
}
Вы не должны использовать это слишком часто в правильно типизированной программе, но это удобно, когда вам это нужно. Пример использования: предположим, что вы внедряете драйвер базы данных, вам, возможно, придется делать преобразования в зависимости от типа переменных Go. Здесь извлечение драйвера go-sql/mysql:
// Scan implements the Scanner interface.
// The value type must be time.Time or string / []byte (formatted time-string),
// otherwise Scan fails.
func (nt *NullTime) Scan(value interface{}) (err error) {
if value == nil {
nt.Time, nt.Valid = time.Time{}, false
return
}
switch v := value.(type) {
case time.Time:
nt.Time, nt.Valid = v, true
return
case []byte:
nt.Time, err = parseDateTime(string(v), time.UTC)
nt.Valid = (err == nil)
return
case string:
nt.Time, err = parseDateTime(v, time.UTC)
nt.Valid = (err == nil)
return
}
nt.Valid = false
return fmt.Errorf("Can't convert %T to time.Time", value)
}