模块 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=true | v = 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+ 类型 → 类型开关。