在Go语言中接口(interface)是一种类型,一种抽象的类型。
我们编写一个猫,一个狗的结构体。
然后编写一个吃饭的函数,可以接收,猫或者狗的结构体,让猫的表现行为吃鱼,狗的表现行为为吃骨头
用传统的方法,无法实现一个参数既是猫也是狗
此时我们就需要把他们的公共方法提取到接口。在定义一个吃饭的接口
type cat struct{}
type dog struct{}
//错误:func meal(c cat|dog) { fmt.Println("猫|狗~") }
例子代码:
2.接口细节
接口中只可以定义方法
type 接口名 interface{
方法名1(参数1,参数2...)(返回值1,返回值2...)
方法名2(参数1,参数2...)(返回值1,返回值2...)
}
变量,参数,返回值可以设置为接口类型
Go 中没有关键字显式声明某个类型实现了某个接口。只要一个类型实现了接口要求的所有方法,该类型就自动被认为实现了该接口。
空接口定义为 interface{}
,可以表示任何类型。
一个未初始化的接口变量其值为 nil
,且不包含任何动态类型或值。
了解
在Go的内部,一个接口通常由两个字段组成:
-
类型信息(Type):这是一个指向类型描述符的指针,包含了接口的具体类型信息。
-
数据(Value):这是一个指向实际数据的指针,这个数据是实现接口的对象的实际数据。
3.结构体,和结构体指针实现接口的区别
我们修改例子代码,让狗的指针实现接口方法
此时,狗的结构体不能当做接口。提示(变量狗的类型,没有实现eat方法,方法eating是一个指针的接受者)
对于猫的结构体实现接口,编译器在接收到指针时候,给我们做了优化,在实际调用时候,给我们加上了指向。
总结
package main
import "fmt"
type eat interface {
change()
}
type cat struct {
id int
name string
}
func (c cat) change() {
c.name = "修改"
fmt.Println("我是方法中的猫", c)
}
func runMyf(e eat) {
e.change()
}
func main() {
var c = &cat{
1, "小花",
}
runMyf(c) //传递的是指针,实际接收是结构体,
// 此时编译器相当于给我们调用了runMyf(*c)
fmt.Println(c)
//打印结果:我是方法中的猫 {1 修改}
//&{1 小花}
}
接口可以嵌套
type eat interface {
eating()
}
type speek interface {
speaking()
}
type animal interface {
eat // eat接口嵌入到animal接口
speek // speek接口嵌入到animal接口
}
type cat struct{}
func (c cat) eating() {
fmt.Println("猫吃鱼")
}
func (c cat) speaking() {
fmt.Println("猫喵喵叫")
}
func desc(a animal) {
a.eating()
a.speaking()
}
func main() {
var m cat
desc(m)
}
接口断言
接口类型的变量.(要判断的实际类型)
在swich中,接口类型要判断的实际类型可以接收type。用于判断接口是哪种实际类型
接口与多态
Go 语言通过接口实现多态,允许不同的结构体实现相同的接口方法
package main
import "fmt"
// 定义一个接口
type Speaker interface {
Speak()
}
// Animal结构体实现Speaker接口
type Animal struct {
Name string
}
func (a Animal) Speak() {
fmt.Println(a.Name, "makes a sound.")
}
// Dog结构体实现Speaker接口
type Dog struct {
Animal
Breed string
}
func (d Dog) Speak() {
fmt.Println(d.Name, "barks.")
}
// Cat结构体实现Speaker接口
type Cat struct {
Name string
}
func (c Cat) Speak() {
fmt.Println(c.Name, "meows.")
}
func main() {
var s Speaker
a := Animal{Name: "Generic Animal"}
d := Dog{Animal: Animal{Name: "Buddy"}, Breed: "Golden Retriever"}
c := Cat{Name: "Whiskers"}
s = a
s.Speak() // 输出: Generic Animal makes a sound.
s = d
s.Speak() // 输出: Buddy barks.
s = c
s.Speak() // 输出: Whiskers meows.
}
在这个示例中,Animal
、Dog
和 Cat
都实现了 Speaker
接口的 Speak
方法。通过接口类型 Speaker
,可以存储任何实现了该接口的结构体,实现多态行为。