Утверждения типов и переключатели типов
Безопасные утверждения типов и шаблоны 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 — локальная установка не требуется.
Все уроки этого курса
- Определение и реализация интерфейсов
- Интерфейсы основной библиотеки
- Утверждения типов и переключатели типов
- Композиция интерфейсов и лучшие практики