golang 接口
1、自定义类型存入接口的内存布局
接口值是一个两个字节长度数据结构,第一个字节包含一个指向内部表的指针(iTable),包含了存储的值的类型信息及和这个值判刑的一组方法。第二个字节指向所存储值的指针。 如果将指针赋值给接口,则类信息会存储一个指向保存的类型的指针,接口的第二个字节依旧保存指向实体值的指针。(图B)
图A
图B
2、方法接收者(方法集) 为什么会有这种限制? 因为编译器并不是总能自动获得一个值的地址。例如:自定义类型,type Integer int,就获取不到Integer 类型值的地址
package main import "fmt" //user 结构 type user struct { name string email string } //sendMail 方法绑定在user 上 func (u user) sendMail() { fmt.Printf("send mail to %s,%s n",u.name,u.email) } //printName 方法绑定在user 指针上 func (u *user) printName() { fmt.Printf("user name %s n",u.name) } func main() { u := user{"zhangsan","xxx@gmail.com"} u.sendMail() u.printName() u2 := &user{"zhangsan2","xxx2@gmail.com"} u2.sendMail() u2.printName() }3、接口实现 方法集:方法集定义了一组关联到给定类型的值或者指针的方法。定义方法时使用的接收者的类型决定了这个方法的关联到的值,还是关联到指针,还是两个都关联。 GO 语言规范定义的方法集规则:T 类型的方法集只包含值接收者声明的方法, *T 类型的方法集包含值接收声明的方法,也包含指针接收者声明的方法。也就是说:如果 *T 接收者来实现的一个接口,只有指向 T 类型的指针才能够实现接口。T 接收者来实现接口,那么T 和 *T 类型都能够实现了这个接口。 示例代码: package main import "fmt" /** user 类型 */ type user struct { name string email string } /** user 实现接口 */ type notify interface { notify() } type notify2 interface { notify2() } /** user 指针实现了 notify 接口 */ func (u *user) notify() { fmt.Printf("notify to user %s n",u.name) } /** user 实现了 notify 接口 */ func (u user) notify2() { fmt.Printf("notify2 to user %s n",u.name) } /** notify 方法,接收对数是notify 接口 */ func notifyMethod(n notify) { n.notify() } func notifyMethod2(n notify2) { n.notify2() } func main() { u := user{"zhangsan","xxx@gmail.com"} //不能将user 类型作为 notify 类型传递给 notifyMethod 方法,user 并没有实现 notify 接口 //notifyMethod(u) //这样传递才可以 notifyMethod(&u) //user 实现了 notify2 接口,那么在user 或者 *user 都实现了此接口 notifyMethod2(u) notifyMethod2(&u) }注:示例中notifyMethod 函数是多态函数,只要实现了notify 接口,那么这个函数可以针对任意实体类型来执行notify 方法,这就是多态。 4、类型嵌套接口实现 内部类型接口的实现会被自动提升到外部类型。如果外部类型也实现了相同的接口,那么就内部类型的实现就不会被提升。 示例代码: package main import "fmt" /** user 类型 */ type user struct { name string email string } /** 类型嵌套 */ type admin struct { user level int } /** 接口 */ type notify interface { notifyToEmail() } /* *user 实现接口 */ func (u *user) notifyToEmail() { fmt.Printf("send mail %s to user %s n",u.email,u.name) } /** 多态方法 */ func notifyMethod(n notify) { n.notifyToEmail() } func main() { //创建一个admin a := admin{ user: user{"name","xxx@gmail.com"},level: 1,} //由于内部类型的提升,内部类型实现的接口会自动提升到外部类型。所有 *admin 类型也实现了notify 接口。 //如果 *admin 实现notify 接口,则内部类型的实现就不会被提升 notifyMethod(&a) } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |