Go语言入门17:接口

Keywords: #技术 #Golang #Go入门笔记
Table of Contents

Go 语言入门基础学习笔记之 Go 语言的接口

golang

接口

Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何结构体只要拥有了这些成员方法,我们就说这个结构体实现了这个接口

本质上接口是一个指针,指向所包含的函数列表。因此接口也是一个引用数据类型,在函数中直接传递原来的变量。

接口可以让我们将不同的类型绑定到一组公共的方法上,从而实现多态灵活的设计。

Go 语言中的接口是隐式实现的,也就是说,如果一个类型实现了一个接口定义的所有方法,那么它就自动地实现了该接口。因此,我们可以通过将接口作为参数来实现对不同类型的调用,从而实现多态

我们可以通过一下代码来检查这个类型是否实现了接口

var _ Interface = (*Type)(nil)

如果没有实现,则会抛出一个具体的错误,方便定位出错的地方。

接口是一组方法的集合,与结构体不同的是,接口中不放成员变量,只放置方法。

实现接口中定义的所有方法,是实现(成为)这个接口的必须条件。

如果定义了一个空接口,则任何类型都实现(成为)了这个接口,相对于其他语言中的 object

Go 语言自带了一个空接口类型 any,任何数据类型都属于一种 any

/* 定义接口 */
type interface_name interface {
   method_name1 [return_type]
   method_name2 [return_type]
   method_name3 [return_type]
   ...
   method_namen [return_type]
}

/* 定义结构体 */
type struct_name struct {
   /* variables */
}

/* 实现接口方法 */
func (struct_name_variable struct_name) method_name1() [return_type] {
   /* 方法实现 */
}
...
func (struct_name_variable struct_name) method_namen() [return_type] {
   /* 方法实现*/
}

实例 1:

package main

import "fmt"

// 定义 Animal 接口,包含两个方法
type Animal interface {
    Speak() string  // 动物发声方法,返回一个字符串
    Eat(food string) string // 动物吃东西方法,接受食物字符串并返回一个字符串
}
// 定义 Dog 结构体,表示狗
type Dog struct {
    Name string // 狗的名字
}
// 定义 Cat 结构体,表示猫
type Cat struct {
    Name string // 猫的名字
}
// 实现 Animal 接口的方法
// Dog 实现 Animal 接口的 Speak 方法
func (d Dog) Speak() string {
    return "Woof! My name is " + d.Name // 返回狗的叫声和名字
}
// Dog 实现 Animal 接口的 Eat 方法
func (d Dog) Eat(food string) string {
    return d.Name + " is eating " + food // 返回狗正在吃的食物
}
// Cat 实现 Animal 接口的 Speak 方法
func (c Cat) Speak() string {
    return "Meow! My name is " + c.Name // 返回猫的叫声和名字
}
// Cat 实现 Animal 接口的 Eat 方法
func (c Cat) Eat(food string) string {
    return c.Name + " is eating " + food // 返回猫正在吃的食物
}
// describeAnimal 函数展示 Animal 接口的特性
func describeAnimal(a Animal) {
    fmt.Println(a.Speak()) // 调用 Speak 方法,并打印返回值
    fmt.Println(a.Eat("food")) // 调用 Eat 方法,并打印返回值,传入字符串 "food"
}
func main() {
    // 创建一个 Dog 实例
    dog := Dog{Name: "Buddy"}
    // 创建一个 Cat 实例
    cat := Cat{Name: "Whiskers"}
    // 调用 describeAnimal 函数,展示狗的行为
    describeAnimal(dog)
    // 调用 describeAnimal 函数,展示猫的行为
    describeAnimal(cat)
}

// 输出结果
Woof! My name is Buddy
Buddy is eating food     
Meow! My name is Whiskers
Whiskers is eating food

代码说明

  1. 接口定义
    • Animal 接口定义了两个方法 Speak()Eat(string),这两个方法是 Animal 接口的行为特点。
  2. 结构体定义
    • DogCat 结构体分别代表不同的动物,它们都有一个 Name 字段。
  3. 接口方法的实现
    • DogCat 都实现了 Animal 接口的方法。这展示了多态性,即不同的类型可以通过相同的接口进行操作。
  4. 接口展示
    • describeAnimal 函数接受一个 Animal 类型的参数,可以接收实现了 Animal 接口的任何类型,展示了接口的灵活性和可扩展性。
  5. 主函数
    • main 函数中,创建了 DogCat 的实例,并调用 describeAnimal 函数,展示了不同动物的行为。

实例 2:

package main

import "fmt"

// 定义一个 Shape 接口,包含一个计算面积的方法
type Shape interface {
    area() float64 // 声明 area 方法,返回值为 float64
}
// 定义一个 Rectangle 结构体,表示矩形
type Rectangle struct {
    width  float64 // 矩形的宽度
    height float64 // 矩形的高度
}
// 为 Rectangle 结构体实现 area 方法
func (r Rectangle) area() float64 {
    return r.width * r.height // 返回矩形的面积
}
// 定义一个 Circle 结构体,表示圆形
type Circle struct {
    radius float64 // 圆形的半径
}
// 为 Circle 结构体实现 area 方法
func (c Circle) area() float64 {
    return 3.14 * c.radius * c.radius // 返回圆形的面积,使用 π ≈ 3.14
}
func main() {
    var s Shape // 声明一个 Shape 类型的变量 s
    // 将 s 指向一个 Rectangle 实例
    s = Rectangle{width: 10, height: 5}
    // 调用 area 方法并打印矩形的面积
    fmt.Printf("矩形面积: %f\n", s.area())
    // 将 s 指向一个 Circle 实例
    s = Circle{radius: 3}
    // 调用 area 方法并打印圆形的面积
    fmt.Printf("圆形面积: %f\n", s.area())
}

// 输出结果
矩形面积: 50.000000
圆形面积: 28.260000

以上实例中,我们定义了一个 Shape 接口,它定义了一个方法 area(),该方法返回一个 float64 类型的面积值。然后,我们定义了两个结构体 RectangleCircle,它们分别实现了 Shape 接口的 area() 方法。在 main() 函数中,我们首先定义了一个 Shape 类型的变量 s,然后分别将 RectangleCircle 类型的实例赋值给它,并通过 area() 方法计算它们的面积并打印出来。

需要注意的是,接口类型变量可以存储任何实现了该接口的类型的值。在示例中,我们将 RectangleCircle 类型的实例都赋值给了 Shape 类型的变量 s,并通过 area() 方法调用它们的面积计算方法。


参考课程:

  1. 8小时转职Golang工程师
  2. Go语言教程 | 菜鸟教程