Go 语言快速入门指南:接口(一)
1. 接口是什么?
接口 是一组仅包含方法名
、参数
、返回值
的未具体实现的方法的集合
,它像是一个公司里面的领导,他会定义一些通用规范,只设计规范,而不实现规范。
Go
语言中接口是一种抽象
的类型。
Go
语言的接口遵守LSP
(里氏替换原则),即 一个类型可以自由地被另一个满足相同接口的类型替换。
2. 为什么需要接口?
大多情况下,一些数据可能包含不同的类型,但是可能会有一个或者多个共同点,这些共同点就是抽象的基础。
Go
的接口类似c++
的多态,接口相当于实现一个父类,然后派生类具体实现父类的虚函数,最后通过父类指针指向不同的派生类对象去调用那个派生类对象的虚函数,从而实现多态
。
于是乎,接口出现了。接口可以理解为某一个方面的抽象,可以是多对一
的(多个类型实现一个接口),这也是多态
的体现。
举例说明一下,比如三角形,四边形,圆形都能计算面积,那就可以在图形接口中写一个计算面积的方法,然后每一种图形都可以具体去实现它,这样就能计算自己的面积(每种图形计算面积的公式不同)了,大概就是这个意思。
3. 接口的定义
type 接口类型名 interface{
方法名1( 参数列表1 ) 返回值列表1
方法名2( 参数列表2 ) 返回值列表2
…
}
Go
语言的接口在命名时,一般会在单词后面添加er
,接口名最好要能突出该接口的类型含义。
Go
语言的接口,是一种新的类型定义
,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口。
4. 接口的实现
一个对象只要全部实现了接口中的方法,那么就实现了这个接口。
//定义一个Sayer接口
type Sayer interface {
say()
}
type dog struct{}
type cat struct{}
//实现接口中具体的方法
func (d dog) say() {
fmt.Println("狗:汪汪")
}
func (c cat) say() {
fmt.Println("猫:喵喵")
}
func main() {
d := dog{} //实例化结构体
d.say()
c := cat{}
c.say()
}
注意:
- 一个类型可以同时实现多个接口,而接口间彼此独立,不知道对方的实现。
Go
语言中不同的类型可以实现同一个接口。
5. 接口的值类型和指针类型
这个本质上和方法的值类型接收和指针类型接收
的思考方法是一样的,值接收是一个拷贝,是一个副本,而指针接收,传递的是指针。
定义一个Pet
接口
type Pet interface {
eat()
}
定义一个Dog结构体
type Dog struct {
name string
}
实现Pet
接口(接收者是值类型)
func (dog Dog) eat() {
fmt.Printf("dog: %p\n", &dog)
fmt.Println("dog eat..")
dog.name = "黑黑"
}
运行示例:
func main() {
dog := Dog{name: "花花"}
fmt.Printf("dog: %p\n", &dog)
dog.eat()
fmt.Printf("dog: %v\n", dog)
}
运行结果:
dog: 0xc000046240
dog: 0xc000046250
dog eat..
dog: {花花}
从运行结果,我们看出dog
的地址变了,说明是复制了一份,dog
的name
没有变说明,外面的dog
变量没有被改变。
将Pet
接口改为指针接收
func (dog *Dog) eat() {
fmt.Printf("dog: %p\n", dog)
fmt.Println("dog eat..")
dog.name = "黑黑"
}
再次运行:
func main() {
dog := &Dog{name: "花花"}
fmt.Printf("dog: %p\n", dog)
dog.eat()
fmt.Printf("dog: %v\n", dog)
}
运行结果:
dog: 0xc00008c230
dog: 0xc00008c230
dog eat..
dog: &{黑黑}
6. 类型与接口关系
- 一个类型可以实现多个接口
- 多个类型可以实现同一个接口(多态)
下一篇我们继续探索 Go
语言接口的更多知识。
时间紧迫,Go语言的接口并不止这些,敬请期待:下一篇:接口(二)
转载自:https://juejin.cn/post/7129489265070702600