接口类型(Interface Type)和接口值(Interface Value)
1. 接口类型(Interface Type)
接口类型定义了一组方法的集合,描述了实现该接口的类型所需的行为
它只是一个类型声明,指定了实现接口的类型必须包含哪些方法,而没有实现具体的功能。
在 Go 中,接口类型是通过 type InterfaceName interface {}
语法来定义的。例如:
type Speaker interface {
Speak() string
}
在上面的代码中,Speaker
是一个接口类型,表示所有实现 Speak
方法的类型都可以被视为 Speaker
类型。
这种方式允许 Go 实现一种“隐式”接口,类型只需实现了接口中的所有方法,就被视为满足该接口。
2. 接口值(Interface Value)
接口值是在接口类型的变量中存储的具体值。接口值由两个部分组成:
- 动态类型:接口值的动态类型表示该接口当前所持有的具体类型(即实现了接口的类型)。
- 动态值:接口值的动态值表示该具体类型的实际值。
当一个接口变量持有一个具体类型的值时,这个值就是该接口的接口值。
示例:接口值的动态类型和动态值
type Speaker interface {
Speak() string
}
type Dog struct{}
func (d Dog) Speak() string {
return "Woof!"
}
func main() {
var s Speaker // 声明一个接口类型变量
s = Dog{} // 为接口赋值一个具体类型的值
fmt.Println(s.Speak()) // 输出: Woof!
}
在这个例子中:
Speaker
是一个接口类型。s
是一个接口类型的变量。
3. 接口值的动态类型与动态值关系
当一个接口变量没有被赋予任何实现类型的值时,它的动态类型和动态值都为 nil
。
一旦为接口变量赋予了一个具体的值,接口的动态类型和动态值都会相应变化。
示例:接口值的 nil
值
func describe(i interface{}) {
fmt.Printf("(%v, %T)\n", i, i)
}
func main() {
var s Speaker // 声明一个接口变量
describe(s) // 输出: (<nil>, <nil>)
s = Dog{}
describe(s) // 输出: ({}, main.Dog)
}