接口实现原理和类型转换
- 接⼝命名习惯以 er 结尾,结构体。
- 接⼝只有⽅法签名,没有实现。
- 接⼝没有数据字段。
- 可在接⼝中嵌⼊其他接⼝。
- 类型可实现多个接⼝。
原理
接⼝对象由接⼝表 (interface table) 指针和数据指针组成
struct Iface
{
Itab* tab;
void* data;
};
示例:使用接口访问对象
type User struct {
id int
name string
}
func main() {
u := User{1, "Tom"}
var i interface{} = u
fmt.Printf("%v\n", i.(User))
}
接口转换
示例一:判断对象的具体接口或类型
type User struct {
id int
name string
}
func (self *User) String() string {
return fmt.Sprintf("%d, %s", self.id, self.name)
}
func main() {
var o interface{} = &User{1,"tom"}
switch v := o.(type) {
case nil: //o == nil
fmt.Println(nil)
case fmt.Stringer: //interface
fmt.Println(v)
case func() string: //func
fmt.Println(v())
case *User: //*struct
fmt.Printf("%d, %s\n", v.id, v.name)
default:
fmt.Println("unkown")
}
}
示例二:超级接口转换为子集接口
type Stringer interface { //子集接口
String() string
}
type Printer interface { //超集接口
Stringer
Print()
}
type User struct {
id int
name string
}
func (self *User) String() string {
return fmt.Sprintf("%d, %s", self.id, self.name)
}
func (self *User) Print() {
fmt.Println(self.String())
}
func main() {
var o Printer = &User{1,"tom"}
var s Stringer = o //超集接口转子集接口
fmt.Println(s.String())
}