跳转到主要内容
模块 6 · 第 3 课(共 5)课程中的28/50~10 min
模块课程(3/5)

类型开关

类型开关区分多个可能的类型 接口值。这是 comma ok 的概括,当有 不止一例。

句法

Go
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 nil:
        return "nil"
    default:
        return fmt.Sprintf("altro tipo: %T", v)
    }
}
  • i.(type) 是一种 特殊语法,仅在 switch 内有效。
  • v := ... 将值与当前案例的类型绑定:在 case int 内,v 具有类型 int。
  • default 捕获所有其他类型;其中 v 具有原始接口的类型。
  • case nil 与 nil 动态类型的接口匹配。

“无名”案

如果不需要键入的值,可以省略 v:

Go
switch i.(type) {
case int:
    // you know it's an int, but you don't have a variable of that type
case string:
    // ...
}

只需要判别类型,不需要操作时使用的一种形式 关于价值。

同一案例中的多种类型

Go
switch v := i.(type) {
case int, int64:
    // here v is still interface{}: the "common" type is just the interface
    fmt.Println("numero intero:", v)
case string:
    // here v is string
    fmt.Println("stringa:", v)
}

典型用例:格式化打印

Go
func print(i interface{}) {
    switch v := i.(type) {
    case int:
        fmt.Printf("%d\n", v)
    case string:
        fmt.Printf("%s\n", v)
    case fmt.Stringer:
        fmt.Println(v.String())
    default:
        fmt.Printf("%v\n", v)
    }
}

fmt.Println 本身在内部使用类型开关来处理 标准格式。

类型开关与反射

对于一些已知类型→类型开关(快速、可读)。 用于动态检查未知类型 → reflect 包(更多 功能强大,但速度较慢且更冗长)。

尝试一下

锻炼#go.m6.l3.e1
尝试:0加载中...

实现描述(i接口{})字符串,根据动态类型返回“int”,“string”或“altro”。

正在加载编辑器...
显示提示

语法:`switch i.(type) { case T: ... default: ... }`。

3 次尝试后可用的解决方案

锻炼#go.m6.l3.e2
尝试:0加载中...

编写使用 v := i.(type) 的 printVal(i interface{}) 并用 %d 表示 int,%s 表示字符串。

正在加载编辑器...
显示提示

在 `case int` 中,v 具有 int 类型(您可以将其传递给 Printf)。

3 次尝试后可用的解决方案

Quiz#go.m6.l3.e3
准备好

哪种语法启动类型切换?

Go
switch ??? {
  case int: ...
}
答案选项

回顾

  • switch v := i.(type) { case T: ... }:区分动态类型。
  • 在单一类型的情况下,v 具有该情况的类型。
  • case T1, T2:v 保留原始接口的类型。
  • default 用于未处理的情况; case nil 用于 nil 接口。
  • 类型开关中没有 fallthrough。
  • 1 类型 → 类型断言; 2+ 类型 → 类型开关。