请考虑以下代码:

type Rectangle struct {
    Width, Height, Area int
}

type Square struct {
    Side, Area int
}

type Geometry struct {
    Area int
}

func SumGeometries(geometries ...Geometry) (sum int) {
    for _, g := range geometries {
        sum += g.Area
    }
    return
}

func TestSumGeometries(t *testing.T) {
    rect := Rectangle{5, 4, 20}
    square := Square{5, 25}

    got := SumGeometries(rect, square)      // cannot use rect (variable of type Rectangle) as Geometry value in argument to MyFunc compilerIncompatibleAssign
    want := 45

    if got != want {
        t.Error("fail!")
    }
}

I want MyFunc to take whatever struct that contains Apple, not just BStruct in specific.
Is this achievable in Go?

我能找到自动取款机的唯一方法是:

type Rectangle struct {
    Width, Height, Area int
}

func (r *Rectangle) GetArea() int {
    return r.Area
}

type Square struct {
    Side, Area int
}

func (s *Square) GetArea() int {
    return s.Area
}

type Areaer interface {
    GetArea() int
}

func SumGeometries(geometries ...Areaer) (sum int) {
    for _, s := range geometries {
        sum += s.GetArea()
    }
    return
}

func TestArgs(t *testing.T) {
    rect := Rectangle{5, 4, 20}
    square := Square{5, 25}

    got := SumGeometries(&rect, &square)        // cannot use rect (variable of type Rectangle) as Geometry value in argument to MyFunc compilerIncompatibleAssign
    want := 45

    if got != want {
        t.Error("fail!")
    }
}

这感觉可能不太惯用:当我已经对消费者直接访问数据感到满意时,我会想用不必要的方法污染我的 struct 吗?

推荐答案

将方法添加到它不会"污染"的类型.

但有一种方法可以在不重复的情况下实现你想要的.使用GetArea()方法定义一个包含公共(此处为Area)字段的Area类型:

type Area struct {
    Value int
}

func (a Area) GetArea() int {
    return a.Value
}

并将其嵌入到其他类型中:

type Rectangle struct {
    Width, Height int
    Area
}

type Square struct {
    Side int
    Area
}

这样,GetArea()方法得到promoted,RectangleSquare将自动实现Areaer.测试:

rect := Rectangle{5, 4, Area{20}}
square := Square{5, Area{25}}

got := SumGeometries(rect, square)

want := 45

if got != want {
    fmt.Println("fail!")
}

不输出任何内容(无错误).在Go Playground号公路上试试.

注意,如果Area只包含一个字段,您甚至可以省略包装器 struct ,直接使用int作为底层类型:

type Area int

func (a Area) GetArea() int {
    return int(a)
}

那么使用它就更简单了:

rect := Rectangle{5, 4, 20}
square := Square{5, 25}

Go Playground号公路上试试这件吧.

Go相关问答推荐

"k8s.io/apimachinery/pkg/runtime.对象(缺少方法DeepCopyBody)

Golang Cososdb-gremlin连接

Go-Colly:将数据切片为POST请求

编辑时保留YAML文件中的单引号

Golang使用Run()执行的命令没有返回

GO:如何指定类型约束,使S方法的参数类型与接收方的参数类型相同

CURL和Postman HTTP POST工作,但Golang请求失败,状态为400

这是go语言gin提供的关于TypeEngine和RouterGroup的问题

按位移计算结果中的差异

如何在 `hashicorp / terraform-exec` 中将 `ApplyConfig` 传递给 `tf.Apply()`?

使用 LINQ 对内部数组进行排序

没有任务角色的 AWS CDK ECS 任务定义

如何确定作为函数参数传递的指针是否正在被修改或副本是否正在被修改?

Go Colly 如何找到请求的元素?

数据流中的无根单元错误,从 Golang 中的 PubSub 到 Bigquery

为什么当我忽略 template.New() 程序可以成功运行?

如何在 Golang 中使用具有相同名称或特定关键字的行或列重新排列/排序 CSV

退格字符在围棋操场中不起作用

手动下载并放置一个 golang mod 文件

在 etcd 键值存储中禁用历史记录