[英]How can I loop over values of different struct types and call the same method on each?
package main
import (
"fmt"
"math"
)
type Rect struct {
width float64
height float64
}
type Circle struct {
radius float64
}
func (r Rect) Area() float64 {
return r.width * r.height
}
func (c Circle) Area() float64 {
return math.Pi * c.radius * c.radius
}
func main() {
rect := Rect{5.0, 4.0}
cir := Circle{5.0}
fmt.Printf("Area of rectangle rect = %0.2f\n", rect.Area())
fmt.Printf("Area of circle cir = %0.2f\n", cir.Area())
}
这是结构的基本常见示例。 但我的问题是如何在多个时运行具有相同名称的 struct 方法。
在这个例子中,有 2 个结构体。 但是如果有 50 个结构体(Circle, Rect, Foo, Bar ....)
并且它们都有一个同名的方法(Area)
。 我如何同时动态地在循环中运行这些方法?
也许我需要一个接口。 我不知道。
使用带有 Area 方法的接口切片:
shapes := []interface{ Area() float64 }{Rect{5.0, 4.0}, Circle{5.0}}
for _, shape := range shapes {
fmt.Printf("Area of %T = %0.2f\n", shape, shape.Area())
}
这实际上是两个问题合二为一:如何创建界面,以及如何并发运行某些东西。
定义接口很简单:
type Shape interface {
Area() float64
}
由于 Go 的魔力,每个定义了Area() float64
函数的类型都会自动实现这个接口。
多亏了这个接口,我们可以将多个形状放入一个切片中:
shapes := []Shape{
Rect{5.0, 4.0},
Circle{5.0},
}
循环这个很容易:
for _, shape := range shapes {
// Do something with shape
}
同时打印的面积真的不是你想要做的事。 它提供了不可预测的输出,其中多行可能混合在一起。 但是让我们假设我们同时计算这些区域,然后在最后将它们全部打印出来:
areas := make(chan float64)
for _, shape := range shapes {
currentShape := shape
go func() { areas <- currentShape.Area() }()
}
for i := 0; i < len(shapes); i++ {
fmt.Printf("Area of shape = %0.2f\n", <-areas)
}
请注意,我们必须如何在循环内的局部变量中捕获currentShape
,以避免它在 goroutine 有机会运行之前更改 goroutine 内部的值。
还要注意我们如何不使用for area := range areas
来消耗通道。 这会导致死锁,因为在所有区域都被写入之后,通道并没有关闭。 还有其他(也许更优雅)的方法来解决这个问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.