# 09.03-Interface

你可能已經注意到，我們可以將 `Rectangle` 的 `area` method 命名為 `Circle` 的 `area` method。這並非意外。在真實世界設計程式時，像這類的相似關係，Go 語言提供了一種所謂的 Interface 型別，這裡有一個 `Shape` 介面的範例：

```go
type Shape interface {
    area() float64
}
```

Interface 與 struct 一樣，都是使用 `type` 關鍵字建立的，後面跟著一個名稱，以及關鍵字 `interface`。不過這裡不定義欄位，而是定義一組 method，一組 method 指的是一串 methods，為了要實做 interface，所以這些 methods 都要有一個型別。

在我們的 `Rectangle` 與 `Circle` 範例中，都有 area method，而且會傳回 `float64`，所以這兩個型別都有實做 `Shape` interface。對它自己本身而言，這樣做並不會有什麼好處，不過我們可以使用 interface 型別做為函式的參數：

```go
func totalArea(shapes ...Shape) float64 {
    var area float64
    for _, s := range shapes {
        area += s.area()
    }
    return area
}
```

我們會像這樣呼叫這個函式：

```go
fmt.Println(totalArea(&c, &r))
```

也可以將 interface 做為欄位使用：

```go
type MultiShape struct {
    shapes []Shape
}
```

我們甚至可以透過提供 MultiShape 一個 area method，將它自己轉為 `Shape`：

```go
func (m *MultiShape) area() float64 {
    var area float64
    for _, s := range m.shapes {
        area += s.area()
    }
    return area
}
```

現在，一個 `MultiShape` 就包含了 `Circle`、`Rectangle`、或甚至是其它的 `MultiShape`。
