Type assertion и type switch
Хендлер загрузки принимал файл и не знал заранее, откуда тот пришёл: с диска или из облака. Первая версия упала на первом же несовпадении, и Миша переписал разбор источников на безопасную форму.
из интерфейса значение достают обратно через type assertion x.(T) (с проверкой ok) или type switch — единственные способы вернуть конкретный тип.
Type assertion
var a any = "report.pdf"
s := a.(string) // "report.pdf"
i := a.(int) // panic: interface conversion
Assertion проверяет, совпадает ли динамический тип. Если не совпал — паника. Именно так уронился первый обработчик источника: он доставал тип без проверки. Поэтому безопасная форма — с двумя значениями:
s, ok := a.(string)
if !ok {
fmt.Println("там не строка")
}
ok == false — тип не совпал, s — zero value. Эта форма не паникует.
Type switch
Когда вариантов несколько, удобнее type switch — Миша так различает источники файлов:
func describeSource(v any) string {
switch x := v.(type) {
case *S3Client:
return "облако: " + x.Bucket
case *LocalDisk:
return fmt.Sprintf("локальный диск: %s", x.Root)
case nil:
return "источник не задан"
default:
return "неизвестный источник"
}
}
В каждой ветке x имеет конкретный тип — не any, а *S3Client, *LocalDisk и так далее. Порядок веток важен: более конкретные типы должны стоять выше интерфейсов, которым они удовлетворяют.
Assertion на интерфейс
x.(T) работает и с интерфейсным T: достать не конкретный тип, а другой интерфейс — проверить, умеет ли значение больше, чем объявлено:
r, ok := st.(io.Reader) // есть ли у источника метод Read?
Вы узнаете:
- как порядок веток в
switch v.(type)влияет на результат - почему assertion
x.(T)на голом nil паникует
Проверьте себя
case Named стоит выше case *User в type switch. Что вернёт classify(&User{name:"alice"})?
var v any (голый nil). Чему равны s и ok в s, ok := v.(string)?
Какая форма type assertion безопасна?
правильных ответов
Type assertion x.(T) возвращает конкретный тип; с ok — безопасно. Type switch — разбор по типам с конкретными типами в ветках.
10 000 ₽ · 60 минут · онлайн