本文发布于Cylon的收藏册,转载请著名原文链接~
类型断言
类型断言 type assertion 并不是真正的将 interface
类型转换为另一种确定的类型,只是提供了对 interface
类型的值的访问,通常情况下,这是常见的需求
类型断言通过 语法 x.(T)
,这将会确定 x 变量中存储的值是否属于 T 类型,通常场景有两种:
- 如果 T 不是 interface 类型,而是一个具体的类型,那么这次断言将断言 x 的 动态类型是否与 T 相同
- 如果 T 是 interface 类型,这次断言 x 的动态类型是否实现了 T
var x interface{} = "foo"
var s string = x.(string)
fmt.Println(s) // "foo"
s, ok := x.(string)
fmt.Println(s, ok) // "foo true"
n, ok := x.(int)
fmt.Println(n, ok) // "0 false"
n = x.(int) // ILLEGAL
Note:在断言时,x 的类型必须为
interface{}
那么怎么理解 T=interface
和 T != interface
这两句话呢
T != interface
则是一个正常的断言,即 x (interface) 是否等于 T (really type),这里 x 必须为 interface,T 则可以为任意类型而不是变量T=interface
时 不能说是一个断言,而是一个对 interface 的断言,此时 x 必须为 interface,T 也必须为 interface
如下面代码所示:
type s interface {}
// 一个interface类型的变量a
var a interface{}
a = a
a = 1
// 一个int 类型的变量b
var b = 20
b = b
x, ok := a.(s) // 1 true 因为a实现了interface
x, ok := b.(s) // false b 不是interface不能断言
x, ok := a.(int) // 1 true 因为a的值为int
x := a.(string) // 当一个返回参数时将触发panic
类型转换
类型转换 type switch 是指类型断言的应用场景,是通过对一个interface类型的变量进行多次断言,以匹配到真实的数据类型
var x interface{} = "foo"
switch v := x.(type) {
case nil:
fmt.Println("x is nil") // here v has type interface{}
case int:
fmt.Println("x is", v) // here v has type int
case bool, string:
fmt.Println("x is bool or string") // here v has type interface{}
default:
fmt.Println("type unknown") // here v has type interface{}
}
本文发布于Cylon的收藏册,转载请著名原文链接~
链接:https://www.oomkill.com/2023/01/go-type-assertion/
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」 许可协议进行许可。