繁体   English   中英

如何遍历不同结构类型的值并在每个值上调用相同的方法?

[英]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())
}

在 GoLang PlayGround 上运行它

这实际上是两个问题合二为一:如何创建界面,以及如何并发运行某些东西。

定义接口很简单:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM