Материал проходит вычитку — возможны неточности.
Урок 45 из 118

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 паникует
Задание · вопросы

Проверьте себя

Вопрос 1 из 3

case Named стоит выше case *User в type switch. Что вернёт classify(&User{name:"alice"})?

Вопрос 2 из 3

var v any (голый nil). Чему равны s и ok в s, ok := v.(string)?

Вопрос 3 из 3

Какая форма type assertion безопасна?

Итоги

Type assertion x.(T) возвращает конкретный тип; с ok — безопасно. Type switch — разбор по типам с конкретными типами в ветках.

Наш сайт собирает куки. Чтобы тебе было удобнее им пользоваться. Нажимая на кнопку, ты даёшь разрешение собирать куки