> For the complete documentation index, see [llms.txt](https://go.netdpi.net/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://go.netdpi.net/struct_interface/09.02-method.md).

# 09.02-Method

雖然現在的程式碼比初版好了許多，不過我們還可以用一個所謂的 method 特殊型別來大幅改善程式碼：

```go
func (c *Circle) area() float64 {
    return math.Pi * c.r*c.r
}
```

在 `func` 關鍵字與函式名稱之間，我們已經新增了一個 “receiver”，receiver 就像是一個參數，具有名稱與型別，但透過此方式建立函式可讓我們使用 `.` 運算符來呼叫函式：

```go
fmt.Println(c.area())
```

這樣很易於閱讀，我們不再需要 `&` 運算符（Go 語言能自動知道要傳遞一個指標給此 method 的 circle），而且因為此函式只能用在 `Circle`，所以我們可以重新將函式只命名為 `area`。

現在替 rectangle 做同樣的設計：

```go
type Rectangle struct {
    x1, y1, x2, y2 float64
}
func (r *Rectangle) area() float64 {
    l := distance(r.x1, r.y1, r.x1, r.y2)
    w := distance(r.x1, r.y1, r.x2, r.y1)
    return l * w
}
```

`main` 具有：

```go
r := Rectangle{0, 0, 10, 10}
fmt.Println(r.area())
```

#### 嵌入式型別 <a href="#toc-embedded-types" id="toc-embedded-types"></a>

一個 struct 的欄位通常代表有一個關係，例如：一個 `Circle` 有一個 `radius`，假設我們有一個 person 這樣的 struct：

```go
type Person struct {
    Name string
}
func (p *Person) Talk() {
    fmt.Println("Hi, my name is", p.Name)
}
```

而且我們想要建立一個新的 `Android` struct，我們可以這樣寫：

```go
type Android struct {
    Person Person
    Model string
}
```

這是可以運作的，而我們會說這樣宣告的意思是：Android 「是」一個人，而不是說 Android「含有」(「擁有」)一個人。Go 語言透過嵌入式型別（embedded type）提供這類關係，也就是所謂的匿名欄位（anonymous field），嵌入式型別看起來類似這樣：

```go
type Android struct {
    Person
    Model string
}
```

我們使用（`Person`）型別，而且不幫它取名字。當以這個方式定義時，就可以使用這個型別名稱來存取 `Person` struct：

```go
a := new(Android)
a.Person.Talk()
```

不過我們也可以直接在 `Android` 上呼叫任何的 `Person` method：

```go
a := new(Android)
a.Talk()
```

這是一個直觀的關係：人可以說話，而一個 android 是一個人，因此 android 可以說話。
