跳到主要内容

Go 接口

提示
  1. 接口定义方法集合:在 Go 语言中,接口用于定义一组方法,但这些方法没有具体的实现。例如,Shape 接口定义了 area()perimeter() 方法,但没有提供具体实现。
  2. 接口的实现:要使用接口,需要通过结构体(struct)来实现它。实现接口的结构体必须提供接口中所有方法的具体实现。例如,Rectangle 结构体实现了 Shape 接口的 area() 方法。
  3. 多个结构体实现同一接口:在 Go 中,多个结构体可以实现同一个接口。这允许不同的结构体共享相同的接口方法,但各自提供不同的实现。例如,RectangleTriangle 结构体都实现了 Shape 接口。

在 Go 编程中,我们使用接口来存储一组没有实现的方法。也就是说,接口的方法不会有方法体。例如,

type Shape interface {
area() float32
perimeter() float32
}

这里,Shape 是一个接口,包含方法:area()perimeter()。你可以看到这两个方法只有方法签名,没有任何实现。

Go 接口的实现

你可能会想,如果接口中的方法没有任何实现,那么接口有什么用呢?

实际上,要使用接口,我们首先需要通过类型(结构体)来实现它。要实现一个接口,结构体应该为接口的所有方法提供实现。例如,

package main
import "fmt"

// 接口
type Shape interface {
area() float32
}

// 结构体实现接口
type Rectangle struct {
length, breadth float32
}

// 使用结构体实现接口的 area()
func (r Rectangle) area() float32 {
return r.length * r.breadth
}

// 访问接口的方法
func calculate(s Shape) {
fmt.Println("面积:", s.area())
}

// main 函数
func main() {

// 为结构体成员赋值
rect := Rectangle{7, 4}

// 用结构体变量 rect 调用 calculate()
calculate(rect)

}

输出

面积: 28

让我们看看这个程序是如何工作的:

接口实现的工作原理

在上面的示例中,我们创建了一个名为 Shape 的接口,其中有一个方法 area()。这里,我们正在尝试通过 Rectangle 结构体来实现这个接口。

type Rectangle struct {
length, breadth float32
}

现在,为了实现接口,我们为接口的 getArea() 提供了实现。

func (r Rectangle) area() float32 {
return r.length * r.breadth
}

为了访问这个方法,我们创建了一个 calculate() 方法

// 访问接口的方法
func calculate(s Shape) {
fmt.Println("面积: ", s.area())
}

这里,该方法接收一个名为 sShape 变量,并使用它来调用 area() 方法。

由于结构体实现了接口,我们使用结构体变量调用了 calculate()

rect := Rectangle{7, 4}
calculate(rect)

多个结构体实现 Go 接口

在 Go 中,一个接口也可以被多个结构体实现。例如,

package main
import "fmt"

// 接口
type Shape interface {
area() float32
}

// Rectangle 结构体实现接口
type Rectangle struct {
length, breadth float32
}

// Rectangle 为 area() 提供实现
func (r Rectangle) area() float32 {
return r.length * r.breadth
}

// Triangle 结构体实现接口
type Triangle struct {
base, height float32
}

// Triangle 为 area() 提供实现
func (t Triangle) area() float32 {
return 0.5 * t.base * t.height
}

// 访问接口的方法
func calculate(s Shape) float32 {
return s.area()
}

// main 函数
func main() {

// 为结构体成员赋值
r := Rectangle{7, 4}
t := Triangle{8, 12}

// 用结构体变量 rect 调用 calculate()
rectangleArea := calculate(r)
fmt.Println("矩形的面积:", rectangleArea)

triangleArea := calculate(t)
fmt.Println("三角形的面积:", triangleArea)

}

输出

矩形的面积: 28
三角形的面积: 48

在上述示例中,我们使用了两个结构体:RectangleTriangle 来实现接口 Shape

就像之前一样,两个结构体都为 area() 方法提供了实现。

这次 calculate() 通过接口 Shape 调用 area() 并返回它。

因此,对于第一次调用 calculate(r),该方法将调用 Rectanglearea() 方法实现。类似地,对于 calculate(t),该方法将调用 Trianglearea() 方法实现。

如果结构体没有实现接口的所有方法会发生什么?

当一个结构体实现一个接口时,它应该为接口的所有方法提供实现。如果没有实现任何方法,我们将得到一个错误。例如,

package main
import "fmt"

// 接口
type Shape interface {
area() float32
perimeter() float32
}

// Rectangle 结构体实现接口
type Rectangle struct {
length, breadth float32
}

// Rectangle 为 area() 提供实现
func (r Rectangle) area() float32 {
return r.length * r.breadth
}

// 访问接口的方法
func calculate(s Shape) float32 {
return s.area()
}

// main 函数
func main() {

// 为结构体成员赋值
r := Rectangle{7, 4}

// 用结构体变量 rect 调用 calculate()
rectangleArea := calculate(r)
fmt.Println("矩形的面积:", rectangleArea)
}

输出

无法将 r (类型 Rectangle) 用作类型 Shape 的参数给 calculate:
Rectangle 没有实现 Shape (缺少 perimeter 方法)

在上述示例中,Shape 接口有两个方法:area()perimeter()。这里,我们正在尝试通过 Rectangle 结构体来实现接口。

然而,该结构体只为 area() 提供了实现。由于结构体没有实现接口的所有方法,我们得到了一个错误。