Golang 中关于接口的一种妙用
go语言中的接口有一个特性: 类型不需要显式的声明实现了哪一个接口,只要该类型实现了接口的所有方法,就可在实例化的时候直接定义。
https://learnku.com/docs/the-way-to-go/what-is-the-111-interface/3647
类型(比如结构体)实现接口方法集中的方法,每一个方法的实现说明了此方法是如何作用于该类型的:即实现接口,同时方法集也构成了该类型的接口。实现了 Namer 接口类型的变量可以赋值给 ai (接收者值),此时方法表中的指针会指向被实现的接口方法。当然如果另一个类型(也实现了该接口)的变量被赋值给 ai,这二者(译者注:指针和方法实现)也会随之改变。
类型不需要显式声明它实现了某个接口:接口被隐式地实现。多个类型可以实现同一个接口。
实现某个接口的类型(除了实现接口方法外)可以有其他的方法。
一个类型可以实现多个接口。
接口类型可以包含一个实例的引用, 该实例的类型实现了此接口(接口是动态类型)。
即使接口在类型之后才定义,二者处于不同的包中,被单独编译:只要类型实现了接口中的方法,它就实现了此接口。
所有这些特性使得接口具有很大的灵活性。
假如,我们定义了一个接口 Person
,接口定义有 GetName()
和 GetAge()
方法。
然后定义2个类型, Student
和 Teacher
, 代码如下
package main
import "fmt"
type Person interface {
GetName() string
GetAge() uint64
}
type Student struct {
name string
age uint64
}
type Teacher struct {
name string
age uint64
}
接下来,我希望结构体 Student
实现接口 Person
,只需要我们按照 Person
中,定义好 GetName()
和 GetAge()
方法即可。
func (stu *Student) GetName() string{
return stu.name
}
func (stu *Student) GetAge() uint64 {
return stu.age
}
这样就完成了接口实现,可以直接使用, 完整代码 :
package main
import "fmt"
type Person interface {
GetName() string
GetAge() uint64
}
type Student struct {
name string
age uint64
}
type Teacher struct {
name string
age uint64
}
func (stu *Student) GetName() string{
return stu.name
}
func (stu *Student) GetAge() uint64 {
return stu.age
}
func main() {
var wuguozhang Person = &Student{
name: "wuguozhang",
age: uint64(26),
}
fmt.Printf("I'm %s", wuguozhang.GetName())
}
最终会输出 I'm wuguozhang
。
现在问题来了,假如我肚子疼了,现在这一段程序急需交给小明来救火,我希望结构体 Teacher()
也实现接口 Person
。 但是即使我多次叮嘱小明,小明仍然可能忘记,有什么办法可以从程序上约束呢?
只要一行代码!就可以解决这个问题。
var _ Person = (*Teacher)(nil)
这一行代码的意思,是定义一个 Person
类型的匿名变量,其值为把 nil
通过类型转换,转换为 Teacher
。 现在如果 Teacher
没有定义方法 GetName()
和 GetAge()
, 编译将会直接失败,IDE也会给出报错提示。
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。