大佬谁能用最简单易懂的方式描述清楚 go 的接口

大佬谁能用最简单易懂的方式描述清楚go的接口,最近看go的接口看的有点迷糊,希望大佬能够指点迷津,帮我顺一下接口

最佳答案

如果之前学过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)
    //最后输出
    // 手机开始工作了...
    // 李四
    // 手机停止工作了...
    // 相机开始工作了...
    // 张三
    // 相机停止工作了...
}

学的时间不长,可能表述上有些错误。希望可以帮助到你

4年前 评论
讨论数量: 6

如果之前学过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)
    //最后输出
    // 手机开始工作了...
    // 李四
    // 手机停止工作了...
    // 相机开始工作了...
    // 张三
    // 相机停止工作了...
}

学的时间不长,可能表述上有些错误。希望可以帮助到你

4年前 评论

@guaosi 受教了,感谢感谢 :+1: :+1: :+1:

4年前 评论

golang 接口总的来说起了一个规范的作用 当你发布某个程序时 想让使用者可以自定义一些功能 可以声明一个接口供别人去实现 这应该是最简单的理解了

4年前 评论

@Shenhi 嗯嗯 是的了,之前和结构体搞混了 :grinning:,感谢赐教

4年前 评论

emmm,自己的一点理解,希望有用 https://www.cnblogs.com/yahuian/p/11838542...

4年前 评论

其实我觉得golang的接口更像php的抽象类

4年前 评论
可爱的堀北同学 4年前
golang练习生 (作者) 4年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!