如果之前学过PHP或者其他语言,可以知道实现一个接口,不仅需要实现其接口里的方法,也需要使用implements
显式说明其实现了该接口。
go则是duck type,即像鸭子,那它就可以是个鸭子。也就是说,在go中,是要是结构体实现了某个接口指定的方法,那它就是实现了这个接口,不需要使用implements
显式说明。
现在说一下接口优点,最大的莫过于控制反转和解耦。举个例子,比如设计一个发送短信的服务,我想接入阿里云与腾讯云的短信业务,此时应该如何设计比较好?是在最底层通过type分类来区分,还是在上层通过传入不同的服务,来对应发送不同的运营商短信比较优雅?其实看laravel框架上的实现就很明白了。
同时,go中的多态的特性通过接口来展现的。
package main
import "fmt"
type Usb interface {
Start()
Stop()
}
type Phone struct {
Name string
}
func (p Phone) Start() {
p.Name = "张三" //这里对引用传递还是值传递的作用一样生效,所以这里没有变化
fmt.Println("手机开始工作了...")
}
func (p Phone) Stop() {
fmt.Println(p.Name) //李四
fmt.Println("手机停止工作了...")
}
type Carame struct {
Name string
}
func (c *Carame) Start() {
c.Name = "张三" //这里对引用传递还是值传递的作用一样生效,所以这里有变化
fmt.Println("相机开始工作了...")
}
func (c *Carame) Stop() {
fmt.Println(c.Name) //张三
fmt.Println((*c).Name) //张三
fmt.Println("相机停止工作了...")
}
type Computer struct {
}
//Usb是前面定义的接口,这里调用的2个函数,在结构体中一定都要有声明过,否则报错。
func (com *Computer) Working(usb Usb) {
usb.Start()
usb.Stop()
}
func main() {
var phone = Phone{}
phone.Name = "李四"
var carame = Carame{}
carame.Name = "李四"
var computer = Computer{}
//这里传入参数是地址还是对象,需要依靠原结构体里定义的方法来判断(比如Phone结构体)。比如Phone结构体中的start方法是p,此时Working传入对象还是地址都可以。如果是*p,则必须传入地址。与com的类型无关。
computer.Working(&phone)
computer.Working(&carame)
//最后输出
// 手机开始工作了...
// 李四
// 手机停止工作了...
// 相机开始工作了...
// 张三
// 相机停止工作了...
}
学的时间不长,可能表述上有些错误。希望可以帮助到你
如果之前学过PHP或者其他语言,可以知道实现一个接口,不仅需要实现其接口里的方法,也需要使用implements
显式说明其实现了该接口。
go则是duck type,即像鸭子,那它就可以是个鸭子。也就是说,在go中,是要是结构体实现了某个接口指定的方法,那它就是实现了这个接口,不需要使用implements
显式说明。
现在说一下接口优点,最大的莫过于控制反转和解耦。举个例子,比如设计一个发送短信的服务,我想接入阿里云与腾讯云的短信业务,此时应该如何设计比较好?是在最底层通过type分类来区分,还是在上层通过传入不同的服务,来对应发送不同的运营商短信比较优雅?其实看laravel框架上的实现就很明白了。
同时,go中的多态的特性通过接口来展现的。
package main
import "fmt"
type Usb interface {
Start()
Stop()
}
type Phone struct {
Name string
}
func (p Phone) Start() {
p.Name = "张三" //这里对引用传递还是值传递的作用一样生效,所以这里没有变化
fmt.Println("手机开始工作了...")
}
func (p Phone) Stop() {
fmt.Println(p.Name) //李四
fmt.Println("手机停止工作了...")
}
type Carame struct {
Name string
}
func (c *Carame) Start() {
c.Name = "张三" //这里对引用传递还是值传递的作用一样生效,所以这里有变化
fmt.Println("相机开始工作了...")
}
func (c *Carame) Stop() {
fmt.Println(c.Name) //张三
fmt.Println((*c).Name) //张三
fmt.Println("相机停止工作了...")
}
type Computer struct {
}
//Usb是前面定义的接口,这里调用的2个函数,在结构体中一定都要有声明过,否则报错。
func (com *Computer) Working(usb Usb) {
usb.Start()
usb.Stop()
}
func main() {
var phone = Phone{}
phone.Name = "李四"
var carame = Carame{}
carame.Name = "李四"
var computer = Computer{}
//这里传入参数是地址还是对象,需要依靠原结构体里定义的方法来判断(比如Phone结构体)。比如Phone结构体中的start方法是p,此时Working传入对象还是地址都可以。如果是*p,则必须传入地址。与com的类型无关。
computer.Working(&phone)
computer.Working(&carame)
//最后输出
// 手机开始工作了...
// 李四
// 手机停止工作了...
// 相机开始工作了...
// 张三
// 相机停止工作了...
}
学的时间不长,可能表述上有些错误。希望可以帮助到你
推荐文章: