1,接口使用一个名为itab的结构存储运行期所需的相关类型信息
type iface struct {
tab *itab //类型信息
data unsafe.Pointer //实际对象指针
}
type itab struct {
inter *interfacetype //接口类型
_type *_type //实际对象类型
fun []uintptr //实际对象方法地址
}
2,利用调试器,可以查看这些结构存储的具体内容
type Ner interface {
a()
b(int)
c(string) string
}
type N int
func(N) a(){}
func(*N)b(int) {}
func(*N)c(string) string {return ""}
func main() {
var n N
var t Ner = &n
t.a()
}
3,对象赋值给接口变量时,会复制该对象
4,类型推断可将接口还原为原始类型,或用来判断是否实现了某个更具体的接口类型,使用ok-idiom模式,即使失败也不会引发panic
package main
import (
"fmt"
)
type data int
func(d data) String() string {
return fmt.Sprintf("data:%d",d)
}
func main(){
var d data = 15
var x interface{} = d
if n,ok := x.(fmt.Stringer);ok { //转换为更具体的类型
fmt.Println(n)
}
if d2,ok := x.(data);ok { //转换为原始类型
fmt.Println(d2)
}
e:=x.(error)
fmt.Println(e)
}
5,使用switch在多种类型间做出推断匹配,使空接口有更多发挥空间。注意:type switch不支持fallthrought。
package main
import "fmt"
func main (){
var x interface {} = func(x int) string {
return fmt.Sprintf("d:%d",x)
}
switch v:=x.(type) { //局部变量v是类型转换后的结果
case nil:
fmt.Println("nil")
case *int:
fmt.Println(*v)
case func(int)string:
fmt.Println(v(100))
case fmt.Stringer:
fmt.Println(v)
default:
fmt.Println("unknow")
}
}
6,技巧:定义函数类型,让相同签名的函数自动实现某个接口
package main
import "fmt"
type FuncString func() string
func(f FuncString) String() string {
return f()
}
func main (){
var t fmt.Stringer = FuncString(func() string {
return "hello world"
})
fmt.Println(t)
}