很多人对于接口存在的作用仍然不是很清楚:既然定义的结构体的方法就能够实现功能,那为什么还要定义接口这多此一举的步骤呢?实际上,接口的作用在函数的接收参数为接口类型的时候作用尤为明显,接下来看示例就明白了
package main
import "fmt"
type Sender interface {
Send(to string, msg string) error
SendAll(tos []string, msg string) error
}
type EmailSender struct {
}
func (s EmailSender) Send(to, msg string) error {
fmt.Println("发送邮件给:", to, ",消息内容是:", msg)
return nil
}
func (s EmailSender) SendAll(tos []string, msg string) error {
for _, to := range tos {
s.Send(to, msg)
}
return nil
}
type SmsSender struct {
}
func (s SmsSender) Send(to, msg string) error {
fmt.Println("发送短信给:", to, ", 消息内容是:", msg)
return nil
}
func (s SmsSender) SendAll(tos []string, msg string) error {
for _, to := range tos {
s.Send(to, msg)
}
return nil
}
//func do(sender EmailSender) {
func do(sender Sender) {
sender.Send("领导", "工作日志")
}
func main() {
var sender Sender = EmailSender{}
fmt.Printf("%T %v\n", sender, sender) // <nil> <nil>
sender.Send("geek", "早上好")
sender.SendAll([]string{"aa","bb"}, "中午好")
do(sender)
sender = SmsSender{}
do(sender)
}
上面代码块中所定义的do方法接收的参数为接口类型,我们在调用此方法的时候就可以直接传入已经实现此接口的结构体,大家都知道golang中的接口实现是隐式实现的,上面的EmailSender和SmsSender都已经实现了sender接口,因此可以直接调用do函数,如果没有接口的话,我们就要分别设计关于EmailSender的do函数和SmsSender的函数了。
如此看来,接口的作用是不是就可以体现出来了,作为接口的开发人员,只关注方法的签名即可,而不用在乎具体的实现。而对于接口的实现的开发人员,则只需要根据要求实现接口,这样就可以将实现好的结构体作为传参调用接口开发人员编写好的函数了。