0Pricing
Go Academy · Урок

Утверждения типов и переключатели типов

Безопасные утверждения типов и шаблоны switch

«Утверждения типов и переключатели типов» — бесплатный урок Go Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Go Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Go Academy содержит 4 уроков всего.

Утверждения типа

Утверждение типа извлекает конкретное значение из интерфейса. Синтаксис: x.(T):

package main
import "fmt"

func main() {
    var i interface{} = "hello"
    s := i.(string)          // panics if wrong type
    fmt.Println(s, len(s))   // hello 5
}

Безопасное утверждение с двумя значениями

Используйте форму с двумя значениями и проверкой успешности, чтобы избежать паники при несовпадении типов:

package main
import "fmt"

func main() {
    var i interface{} = 42
    s, ok := i.(string)
    fmt.Println(s, ok)  // "" false
    n, ok := i.(int)
    fmt.Println(n, ok)  // 42 true
}

Переключатель типов

Переключатель типов сравнивает динамический тип значения интерфейса с несколькими типами:

package main
import "fmt"

func describe(i interface{}) string {
    switch v := i.(type) {
    case int:    return fmt.Sprintf("int: %d", v)
    case string: return fmt.Sprintf("string: %q", v)
    case bool:   return fmt.Sprintf("bool: %v", v)
    default:     return fmt.Sprintf("unknown: %T", v)
    }
}

func main() {
    fmt.Println(describe(42))
    fmt.Println(describe("hi"))
    fmt.Println(describe(3.14))
}

Переключатель типов для ошибок

Переключатели типов особенно полезны для классификации ошибок:

package main
import ("errors"; "fmt")

type NotFoundError struct{ Name string }
func (e *NotFoundError) Error() string { return e.Name + " not found" }

type PermError struct{}
func (e *PermError) Error() string { return "permission denied" }

func handle(err error) {
    switch e := err.(type) {
    case *NotFoundError: fmt.Println("missing:", e.Name)
    case *PermError:     fmt.Println("perm error")
    default:             fmt.Println("other:", e)
    }
}

func main() {
    handle(&NotFoundError{"user"})
    handle(errors.New("generic"))
}

Утверждение для интерфейса

Можно утверждать принадлежность не только к конкретному типу, но и к другому типу интерфейса. Это полезно для проверки поддержки объектом необязательного поведения:

package main
import "fmt"

type Flusher interface{ Flush() }

type Writer interface{ Write(string) }

type BufferedWriter struct{ buf string }
func (b *BufferedWriter) Write(s string) { b.buf += s }
func (b *BufferedWriter) Flush()         { fmt.Println(b.buf); b.buf = "" }

func maybeFlush(w Writer) {
    if f, ok := w.(Flusher); ok { f.Flush() }
}

func main() {
    bw := &BufferedWriter{}
    bw.Write("hello")
    maybeFlush(bw)
}

Утверждение для нулевого интерфейса

Утверждение для нулевого интерфейса вызывает панику. Всегда проверяйте, что интерфейс не имеет нулевого значения, прежде чем выполнять утверждение:

package main
import "fmt"

func safePrint(i interface{}) {
    if i == nil {
        fmt.Println("nil")
        return
    }
    fmt.Printf("%T: %v\n", i, i)
}

func main() {
    safePrint(nil)
    safePrint(42)
}

Альтернатива для TypeOf из пакета отражения

Чтобы вывести тип без утверждения, используйте fmt.Sprintf("%T", v) или reflect.TypeOf(v):

package main
import ("fmt"; "reflect")

func main() {
    v := []int{1, 2, 3}
    fmt.Printf("%T\n", v)             // []int
    fmt.Println(reflect.TypeOf(v))    // []int
}

Утверждение типа и преобразование типа

Утверждение типа: извлечение конкретного типа из интерфейса. Преобразование типа: изменение одного конкретного типа на другой совместимый тип. Это разные операции:

package main
import "fmt"

func main() {
    var i interface{} = int32(5)
    n := i.(int32)          // assertion — OK
    big := int64(n)         // conversion — OK
    fmt.Println(n, big)
}

Идиома comma-ok в select

Идиома comma-ok также работает при получении значений из каналов, позволяя обнаружить закрытый канал. В Go эта же лаконичная идиома используется последовательно.

Когда использовать переключатели типов

Распространённые варианты использования:

  • Десериализация JSON с полями interface{}
  • Классификация ошибок
  • Диспетчеризация сообщений протокола
  • Проверка необязательных интерфейсов

Быстрая проверка

Каков результат неудачного утверждения типа без безопасной проверки?

Повторение

Основные выводы:

  • x.(T) вызывает панику при неправильном типе; x, ok := x.(T) безопасно
  • Переключатели типов аккуратно обрабатывают несколько типов
  • Выполняйте утверждение типа для интерфейсов, чтобы проверять необязательные возможности
  • Никогда не выполняйте утверждение для интерфейса со значением nil

Практическое задание

Напишите функцию sum(values []any) float64, которая использует переключатель типов для обработки значений типа int, float64 и string (разбирая строку), а остальные значения пропускает.

Часто задаваемые вопросы

Урок «Утверждения типов и переключатели типов» бесплатный?

Да — полный текст урока «Утверждения типов и переключатели типов» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Go Academy, подпишись на CoddyKit PRO. Курс Go Academy содержит 4 уроков всего.

Чему я научусь в уроке «Утверждения типов и переключатели типов»?

Безопасные утверждения типов и шаблоны switch Ты практикуешь Go Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Go Academy?

Предыдущий опыт не требуется. Go Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «Утверждения типов и переключатели типов»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Go Academy?

Да. Каждый урок Go Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Определение и реализация интерфейсов
  2. Интерфейсы основной библиотеки
  3. Утверждения типов и переключатели типов
  4. Композиция интерфейсов и лучшие практики
← Назад к Go Academy