为了账号安全,请及时绑定邮箱和手机立即绑定

Golang:隐式结构匹配

Golang:隐式结构匹配

Go
慕尼黑的夜晚无繁华 2023-02-06 19:01:15
考虑这段代码: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!")    }}我希望 MyFunc 采用包含 Apple 的任何结构,而不仅仅是特定的 BStruct。这在 Go 中可以实现吗?我能找到 ATM 的唯一方法如下: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!")    }}感觉可能不符合习惯:当我已经对消费者直接访问数据感到满意时,我是否想用不必要的方法污染我的结构?
查看完整描述

1 回答

?
忽然笑

TA贡献1806条经验 获得超5个赞

将方法添加到它不会“污染”的类型。


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


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()方法得到提升Rectangle并将Square自动执行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仅包含单个字段,您甚至可以省略包装器结构并int直接用作基础类型:


type Area int


func (a Area) GetArea() int {

    return int(a)

}

然后使用它更简单:


rect := Rectangle{5, 4, 20}

square := Square{5, 25}

在Go Playground试试这个。



查看完整回答
反对 回复 2023-02-06
  • 1 回答
  • 0 关注
  • 117 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信