猿问

Golang:隐式结构匹配

考虑这段代码:


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!")

    }

}

感觉可能不符合习惯:当我已经对消费者直接访问数据感到满意时,我是否想用不必要的方法污染我的结构?


慕尼黑的夜晚无繁华
浏览 118回答 1
1回答

忽然笑

将方法添加到它不会“污染”的类型。但是有一种方法可以在不重复的情况下实现你想要的。使用方法定义一个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 := 45if got != want {    fmt.Println("fail!")}什么都不输出(没有错误)。在Go Playground上尝试一下。请注意,如果Area仅包含单个字段,您甚至可以省略包装器结构并int直接用作基础类型:type Area intfunc (a Area) GetArea() int {    return int(a)}然后使用它更简单:rect := Rectangle{5, 4, 20}square := Square{5, 25}在Go Playground试试这个。
随时随地看视频慕课网APP

相关分类

Go
我要回答