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

类型断言

类型断言从接口值中提取具体类型。 当您有 interface{} (或“高”接口)时,您需要它 手并需要将其视为其特定类型来访问字段或 接口上不存在的方法。

句法

Go
var i interface{} = "ciao"

s := i.(string)           // "panic" form: panics if it's not a string
s, ok := i.(string)       // "comma ok" form: ok = false if it's not a string

两种形式,两种语义:

表格成功失败
v := i.(T)v = T 类型的值运行时恐慌
v, ok := i.(T)v=...、ok=truev = T 的零值,ok=false

“逗号ok”形式:最安全

Go
var i interface{} = 42

if s, ok := i.(string); ok {
    fmt.Println("è stringa:", s)
} else {
    fmt.Println("non è stringa, ignoro")
}

ok 让您可以毫无恐慌地处理“错误类型”的情况。这是 绝大多数情况下都是惯用模式。

对接口的断言

该断言不仅适用于具体类型,还适用于其他类型 接口:

Go
type Closer interface { Close() error }

func tryClose(x interface{}) {
    if c, ok := x.(Closer); ok {
        c.Close()
    }
}

标准库中一个非常常见的模式:“如果我的输入也是 io.Closer,最后调用 Close”。

指针与值的断言

断言必须与动态类型完全匹配:

Go
type Cat struct{}
func (c *Cat) Meow() {}

var a interface{} = &Cat{}

c1, ok := a.(*Cat)   // ok = true
c2, ok := a.(Cat)    // ok = false: it holds *Cat, not Cat

*Cat 和 Cat 是类型系统的不同类型。

何时使用断言与类型开关

  • 只有 1 种可能的类型,“功能检测”检查(例如转换为可选接口):带有 comma ok 的类型断言。
  • 2+可能的类型,在多个分支上分派:类型 switch (下一课)。

尝试一下

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

使用逗号 ok 模式从 i 中提取字符串。

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

语法:`v, ok := i.(T)`。

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

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

将断言键入 int,不带逗号 ok(假设 i 包含 int)。

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

如果没有“ok”,你就假设类型是确定的;否则恐慌。

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

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

如果 i 包含 int ,那么 `s := i.(string)` 会发生什么?

Go
var i interface{} = 42
s := i.(string)
答案选项

回顾

  • v := i.(T):如果动态类型 ≠ T,则发生恐慌。
  • v, ok := i.(T):安全模式,检查ok。
  • 也适用于另一个界面(“功能检测”)。
  • T 和 *T 是断言的不同类型。
  • 1 种类型 → 断言; 2+ 类型 → 类型开关。