1、接口是什么?
在Go语言中,接口是一种类型
。抽象地定义了一组方法签名,但不实现这些方法。接口类型指定了一个值应该有哪些方法,因此,任何具有这些方法的类型都自动满足该接口
。
在 Go 语言的语义上,只要某个类型实现了所定义的一组方法集,则就认为其就是同一种类型,是一个东西。大家常常称其为鸭子类型(Duck typing)
,因为其与鸭子类型类型的定义相对吻合。
一个接口类型的变量可以存储任何实现了该接口的类型的值
。
这里引入了两个概念,动态接口类型
和动态值
。
- 动态类型(Dynamic Type)
动态类型是指接口变量当前实际包含的值的类型。在Go语言中,接口变量在声明时不需要指定它们可以存储的具体类型;相反,接口类型的变量在运行时可以接受和存储任何满足接口定义的类型的值。这个具体的类型,就是接口变量的动态类型。 - 动态值(Dynamic Value)
动态值是接口变量当前实际包含的值。由于Go是静态类型语言,每个变量都有一个静态类型,但是接口变量的特殊之处在于,它们的静态类型是接口自己,而它们的动态值可以是任何满足该接口的类型的实例。
这里其实不太好理解,其实我的理解
就是:
动态类型就是实现了接口的具体类型
。
动态值就是类型的具体实例
。
2、接口怎么使用?
// 接口声明
type Human interface {Say(s string) error
}// 接口实现
type TestA string
func (a TestA) Say(s string) error {fmt.Println(s)return nil
}func main() {var h Humanvar t TestA_ = t.Say("我是benzunyinzi")h = t_ = h.Say("我是本尊银子")
}
主函数 main 中通过声明和赋值,成功将类型为 TestA 的变量 t
赋给了类型为 Human 的变量 h
,也就是说两者只因有了个 Say 方法,在 Go 语言的编译器中就认为他们是 “一样” 的了,这也就是业界中常说的鸭子类型
。
多态
type Human interface {Say(s string) errorSpeak()
}type Cat stringfunc (c Cat) Say(s string) error {fmt.Println(s)return nil
}func (c Cat) Speak()