导入
简介
本节课通过一个示例介绍 Go 语言中的接口,并讲解如何定义一个新类型来实现相同的接口。
定义
接口 类型由一组方法定义。
一个接口类型的值可以持有任何实现了这些方法的值。接口提高了代码的灵活性和可扩展性,因此可用于在 Go 语言中实现多态。接口不要求具体的类型,而是指明只需要某种行为,而这种行为由一组方法来定义。
示例
这是我们之前示例的一个重构版本。
这一次,我们通过定义一个名为 Greet 的函数,使其接受一个接口类型 Namer 的参数,从而使问候功能更加通用。
Namer 是我们定义的新接口,仅包含一个方法:Name()。因此,Greet() 可以接受任何定义了 Name() 方法的值作为参数。
为了让我们的 User 结构体实现该接口,我们定义了一个 Name() 方法。现在就可以调用 Greet 函数,并传入指向 User 类型的指针。
1package main 2 3import ( 4 "fmt" 5) 6 7type User struct { 8 FirstName, LastName string 9} 10 11func (u *User) Name() string { 12 return fmt.Sprintf("%s %s", u.FirstName, u.LastName) 13} 14 15type Namer interface { 16 Name() string // Namer 接口由 Name() 方法定义 17} 18 19func Greet(n Namer) string { 20 return fmt.Sprintf("Dear %s", n.Name()) 21} 22 23func main() { 24 u := &User{"Matt", "Aimonetti"} 25 fmt.Println(Greet(u)) 26}
定义新类型
我们现在可以定义一个新类型,只要它实现了相同的接口,Greet 函数仍然可以正常工作。
1package main 2 3import ( 4 "fmt" 5) 6 7type User struct { 8 FirstName, LastName string 9} 10 11func (u *User) Name() string { // 为 User 类型定义的 Name 方法 12 return fmt.Sprintf("%s %s", u.FirstName, u.LastName) 13} 14 15type Customer struct { 16 Id int 17 FullName string 18} 19 20func (c *Customer) Name() string { // 为 Customer 类型定义的 Name 方法 21 return c.FullName 22} 23 24type Namer interface { 25 Name() string // 两个 Name() 方法都可以通过 Namer 接口调用 26} 27 28func Greet(n Namer) string { 29 return fmt.Sprintf("Dear %s", n.Name()) 30} 31 32func main() { 33 u := &User{"Matt", "Aimonetti"} 34 fmt.Println(Greet(u)) 35 c := &Customer{42, "Francesc"} 36 fmt.Println(Greet(c)) 37}
现在我们已经对 Go 中的接口有了基本理解,接下来将继续学习接口是如何被满足的。