Go的接口与多态
接口可以说是一种类型,可以粗略的理解为他的变量是一堆方法。
一个简单的案例:
r,_ := http.Get("http://www.baidu.com") io.Copy(os.Stdout,r.Body)
其中 io.copy 接受的变量是 io.Writer,io.Reader(实际上是接口类型)
而os.Stdout 和 r.Body 并不是这两种类型,但是他们实现了这两个接口,所以编译器可以识别出这是可行的的。
而 go 是怎么实现接口的呢?
可以假设 io.Reader 是这么写的:
type Reader interface{ funca() funcb() funcc() }
type Body struct{ ... } func (b Body)funca(){ ... } func (b Body)funcb(){ ... } func (b Body)funcc(){ ... }
在go中无需声明要实现什么接口,你只需要实现这个接口的所有方法就是直接显现了这个接口,也就是没有显示的实现接口的这一说法。
这里有一个有意思的地方。
很明显 结构体A 与结构体A 的指针是不同的类型
但 结构体A实现的方法对 A的指针有效,A的指针实现的方法对A无效
package main import "fmt" // duration是一个基于int类型的类型 type duration int // 使用更可读的方式格式化duration值 func (d *duration) pretty() string { return fmt.Sprintf("Duration: %d", *d) } // main是应用程序的入口 func main() { duration(42).pretty() // ./listing46.go:17: 不能通过指针调用duration(42)的方法 // ./listing46.go:17: 不能获取duration(42)的地址 }
多态
go利用接口实现多态的方式 简单粗暴
不同类型实现的同一接口,在接口调用时就会完美的体现出来
// 这个示例程序使用接口展示多态行为 package main import ( "fmt" ) // notifier是一个定义了 // 通知类行为的接口 type notifier interface { notify() } // user在程序里定义一个用户类型 type user struct { name string email string } // notify使用指针接收者实现了notifier接口 func (u *user) notify() { fmt.Printf("Sending user email to %s<%s>\n", u.name, u.email) } // admin定义了程序里的管理员 type admin struct { name string email string } // notify使用指针接收者实现了notifier接口 func (a *admin) notify() { fmt.Printf("Sending admin email to %s<%s>\n", a.name, a.email) } // main是应用程序的入口 func main() { // 创建一个user值并传给sendNotification bill := user{"Bill", "bill@email.com"} sendNotification(&bill) // 创建一个admin值并传给sendNotification lisa := admin{"Lisa", "lisa@email.com"} sendNotification(&lisa) } // sendNotification接受一个实现了notifier接口的值 // 并发送通知 func sendNotification(n notifier) { n.notify() }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通