【Go】Go 语言中的接口

文章目录
一、接口
二、定义接口
三、实例
四、Go语言中文文档中定义的接口
参考链接
一、接口
Go 语言提供了另外一种数据类型:接口(interface),它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口。

接口是一组方法签名的集合,然后我们可以定义一个结构体实现该接口所有方法。因此,接口就是定义了对象的行为。

例如,结构体Dog可以walk和bark, 如果一个接口声明了walk和bark的方法签名,而Dog实现了walk和bark方法,那么Dog就实现了该接口。

接口的主要工作是仅提供由方法名称,输入参数和返回类型组成的方法签名集合。 由类型(例如struct结构体)来声明方法并实现它们。
(如果不在类型上实现接口中的方法,那么接口仍然是一个概念)

如果一个类型实现了在接口中定义的所有声明方法,则称该类型实现了该接口。

我说:
接口只是一个方法的集合(只是一个概念,只是一个概念上的集合)。
接口中声明的方法的具体实现是基于一个类型的(struct结构体)。
如果,实现了定义在某个结构体类型上的多个方法,而所有这些方法恰好组成了一个接口;那么就说该结构体类型实现了该接口。

我再说:
接口是基于类型(结构体)实现的。
可以基于很多不同的类型实现这个接口。(同样,一个类型也可以实现多个接口)
所以声明一个接口之后,要用某个特定的结构体类型来实例化这个接口。(前提:这个特定的结构体类型已经实现了该接口)
然后你就可以用这个接口调用该结构体类型上的所有方法啦。

二、定义接口
/* 定义接口 */
type interface_name interface {
   method_name1 [return_type]
   method_name2 [return_type]
   method_name3 [return_type]
   ...
   method_namen [return_type]
}

/* 定义结构体 */
type struct_name struct {
   /* variables */
}

/* 在结构体上实现接口方法 */
func (struct_variable_name struct_name) method_name1() [return_type] {
   /* 方法实现 */
}
...
func (struct_name_variable struct_name) method_namen() [return_type] {
   /* 方法实现*/
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
说明:

接口名:使用type将接口定义为自定义的类型名。Go语言的接口在命名时,一般会在单词后面添加er,如有写操作的接口叫Writer,有字符串功能的接口叫Stringer等。接口名最好要能突出该接口的类型含义。

方法名:当方法名首字母是大写且这个接口类型名首字母也是大写时,这个方法可以被接口所在的包(package)之外的代码访问。

参数列表、返回值列表:参数列表和返回值列表中的参数变量名可以省略。

三、实例
package main

import (
    "fmt"
)


//定义接口 Phone
//接口 Phone 里有一个方法 call()
type Phone interface {
    call()
}


//定义结构体
type NokiaPhone struct {
}


//在结构体 NokiaPhone 上实现接口方法
func (nokiaPhone NokiaPhone) call() {
    fmt.Println("I am Nokia, I can call you!")
}

type IPhone struct {
}

//在结构体 IPhone 上实现接口方法
func (iPhone IPhone) call() {
    fmt.Println("I am iPhone, I can call you!")
}

func main() {
    //声明了一个新的接口phone 
    var phone Phone

    //用结构体 NokiaPhone 来实例化接口phone 
    //使用 new 函数来为自定义类型分配空间
    phone = new(NokiaPhone)
    //用接口phone调用该结构体上的方法
    phone.call()

    //用结构体 IPhone 来实例化接口phone
    phone = new(IPhone)
    phone.call()

}

1
2
3
4
5

输出结果:

I am Nokia, I can call you!
I am iPhone, I can call you!
1
2
四、Go语言中文文档中定义的接口
接口是什么
接口(interface)定义了一个对象的行为规范,只定义规范不实现,由具体的对象来实现规范的细节。

在Go语言中接口(interface)是一种类型,一种抽象的类型。

实现接口的条件
一个对象只要全部实现了接口中的方法,那么就实现了这个接口。换句话说,接口就是一个需要实现的方法列表。

接口的实现就是这么简单,只要实现了接口中的所有方法,就实现了这个接口。

接口有什么用
先看一个不用接口的例子:

type Cat struct{}

func (c Cat) Say() string { return "喵喵喵" }

type Dog struct{}

func (d Dog) Say() string { return "汪汪汪" }

func main() {
    c := Cat{}
    fmt.Println("猫:", c.Say())
    d := Dog{}
    fmt.Println("狗:", d.Say())
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
上面的代码中定义了猫和狗,然后它们都会叫,你会发现main函数中明显有重复的代码,如果我们后续再加上猪、青蛙等动物的话,我们的代码还会一直重复下去。那我们能不能把它们当成“能叫的动物”来处理呢?

像类似的例子在我们编程过程中会经常遇到:
比如一个网上商城可能使用支付宝、微信、银联等方式去在线支付,我们能不能把它们当成“支付方式”来处理呢?
比如三角形,四边形,圆形都能计算周长和面积,我们能不能把它们当成“图形”来处理呢?
比如销售、行政、程序员都能计算月薪,我们能不能把他们当成“员工”来处理呢?

Go语言中为了解决类似上面的问题,就设计了接口这个概念。接口区别于我们之前所有的具体类型,接口是一种抽象的类型。当你看到一个接口类型的值时,你不知道它是什么,唯一知道的是通过它的方法能做什么。

下面通过一个实例体会一下实现了接口有什么用:

package main

import (
    "fmt"
)

type Sayer interface {
    Say()
}

//声明了一个 Cat 结构体
type Cat struct{}

//在 Cat 结构体上实现方法 Say()
func (c Cat) Say() { fmt.Println("喵喵喵") }

//声明了一个 Dog 结构体
type Dog struct{}

//在 Dog 结构体上实现方法 Say()
func (d Dog) Say() { fmt.Println("汪汪汪") }

func main() {
    var x Sayer // 声明一个Sayer类型的变量x
    a := Cat{}  // 实例化一个cat
    b := Dog{}  // 实例化一个dog
    x = a       // 可以把cat实例直接赋值给x
    x.Say()     // 喵喵喵
    x = b       // 可以把dog实例直接赋值给x
    x.Say()     // 汪汪汪
}


输出结果:

喵喵喵
汪汪汪
1
2
接口类型变量能够存储所有实现了该接口的实例。

例如上面的示例中,Sayer类型的变量能够存储Dog 和Cat 类型的变量。

通过对不同的Sayer调用方法Say,就能让他们说自己的话。
————————————————
版权声明:本文为CSDN博主「想变厉害的大白菜」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_44211968/article/details/121395529

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值