文章目录
一、接口
二、定义接口
三、实例
四、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