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
这在围棋中可以实现吗?

我能找到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!")
}
}

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

向类型添加方法;"污染";。

但是有一种方法可以不重复地实现你想要的。用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()方法得到了推广,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!")
}

无输出(无错误(。在围棋场上试试吧。

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

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

然后使用它更简单:

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

在围棋场上试试这个。

最新更新