09.02-Method
雖然現在的程式碼比初版好了許多,不過我們還可以用一個所謂的 method 特殊型別來大幅改善程式碼:
func (c *Circle) area() float64 {
return math.Pi * c.r*c.r
}
在 func
關鍵字與函式名稱之間,我們已經新增了一個 “receiver”,receiver 就像是一個參數,具有名稱與型別,但透過此方式建立函式可讓我們使用 .
運算符來呼叫函式:
fmt.Println(c.area())
這樣很易於閱讀,我們不再需要 &
運算符(Go 語言能自動知道要傳遞一個指標給此 method 的 circle),而且因為此函式只能用在 Circle
,所以我們可以重新將函式只命名為 area
。
現在替 rectangle 做同樣的設計:
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
具有:
r := Rectangle{0, 0, 10, 10}
fmt.Println(r.area())
嵌入式型別
一個 struct 的欄位通常代表有一個關係,例如:一個 Circle
有一個 radius
,假設我們有一個 person 這樣的 struct:
type Person struct {
Name string
}
func (p *Person) Talk() {
fmt.Println("Hi, my name is", p.Name)
}
而且我們想要建立一個新的 Android
struct,我們可以這樣寫:
type Android struct {
Person Person
Model string
}
這是可以運作的,而我們會說這樣宣告的意思是:Android 「是」一個人,而不是說 Android「含有」(「擁有」)一個人。Go 語言透過嵌入式型別(embedded type)提供這類關係,也就是所謂的匿名欄位(anonymous field),嵌入式型別看起來類似這樣:
type Android struct {
Person
Model string
}
我們使用(Person
)型別,而且不幫它取名字。當以這個方式定義時,就可以使用這個型別名稱來存取 Person
struct:
a := new(Android)
a.Person.Talk()
不過我們也可以直接在 Android
上呼叫任何的 Person
method:
a := new(Android)
a.Talk()
這是一個直觀的關係:人可以說話,而一個 android 是一個人,因此 android 可以說話。
Last updated