Go 接口
- 接口定义方法集合:在 Go 语言中,接口用于定义一组方法,但这些方法没有具体的实现。例如,
Shape
接口定义了area()
和perimeter()
方法,但没有提供具体实现。 - 接口的实现:要使用接口,需要通过结构体(struct)来实现它。实现接口的结构体必须提供接口中所有方法的具体实现。例如,
Rectangle
结构体实现了Shape
接口的area()
方法。 - 多个结构体实现同一接口:在 Go 中,多个结构体可以实现同一个接口。这允许不同的结构体共享相同的接口方法,但各自提供不同的实现。例如,
Rectangle
和Triangle
结构体都实现了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())
}
这里,该方法接收一个名为 s
的 Shape
变量,并使用它来调用 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
在上述示例中,我们使用了两个结构体:Rectangle
和 Triangle
来实现接口 Shape
。
就像之前一样,两个结构体都为 area()
方法提供了实现。
这次 calculate()
通过接口 Shape
调用 area()
并返回它。
因此,对于第一次调用 calculate(r)
,该方法将调用 Rectangle
的 area()
方法实现。类似地,对于 calculate(t)
,该方法将调用 Triangle
的 area()
方法实现。
如果结构体没有实现接口的所有方法会发生什么?
当一个结构体实现一个接口时,它应该为接口的所有方法提供实现。如果没有实现任何方法,我们将得到一个错误。例如,
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()
提供了实现。由于结构体没有实现接口的所有方法,我们得到了一个错误。