接口概念
一个具体类型具体类型的值动态类型动态值
iface
type iface struct{
tab *itab //itab存放类型及方法指针信息
data unsafe.Pointer //数据信息
}
iface
- itab:用来存放接口自身类型和绑定的实例类型及实例相关的函数指针。
- 数据指针data:指向接口绑定的实例的副本,接口的初始化也是一种值拷贝。
空接口的底层数据结构也很简单,代码如下:
type eface struct{
_type *_type
data unsafe.Pointer
}
从eface的数据结构可以看出,空接口不是真的为空,其保留了具体实例的类型和值拷贝,即便存放的具体类型是空的,空接口也不是空的。
可以使用类型断言来判断接口中的值,其语法格式:
x.(T)
// x表示为 interface{}的变量
// T表示断言x可能的类型
xTtruefalse
x.(T)
func main() {
var x interface{
}
x = 666
value,ok := x.(int)
if ok == true{
fmt.Println("断言成功,值为:",value)
}else{
fmt.Println("断言失败,x不是int类型")
}
}
// 运行结果:
// 断言成功,值为:666
x.(type)switch
x.(type)
func checkType(x interface{
}){
switch t := x.(type) {
case string:
fmt.Println("string类型: ",t)
case int:
fmt.Println("int类型: ",t)
case bool:
fmt.Println("bool类型: ",t)
default:
fmt.Println("未知类型")
}
}
func main() {
var x interface{
}
x = 666
checkType(x)
x = "test"
checkType(x)
}
//运行结果:
// int类型: 666
// string类型: test
注意:
x.(type)x.(T)x
例如:
func main() {
var x int //x为int类型
x = 666
v,ok := x.(int)//编译失败,提示invalid type assertion: x.(int) (non-interface type int on left)
if ok == true{
fmt.Println("int ",v)
}else{
fmt.Println("unknow")
}
}
checkType
x interface{}x int
func checkType(x interface{
}){
switch t := x.(type) {
case string:
fmt.Println("string类型: ",t)
case int:
fmt.Println("int类型: ",t)
case bool:
fmt.Println("bool类型: ",t)
default:
fmt.Println("未知类型")
}
}
func main() {
var x int //x为int类型
x = 666
checkType(x)
}
//运行结果:
// int类型: 666