沒有 object、沒有 class 、沒有繼承的 Go,
靠著 struct / method / interface,
好像也享有 OOP 語言的優點呢
今天的筆記依然參考 30天學會Golang 系列,
以及相見恨晚的 A Tour of Go(互動式教學,有 compiler)
明天會是最後一篇小筆記,畢竟 Go 是併發(concurrency)小能手,
還是要了解一下 Goroutines。
之後想想做點實際的 hands on 之類。
本來以為 Go 是物件導向,後來發現沒有 class!
基本上使用 struct 與 method 來達到類似的效果。
method 是一個有 receiver argument 的 function
we can define method on a type. (不一定是 struct,但這個 type 要在同個 package 中,int 這些 built-in type 要先透過 type 關鍵字來定義一個新型別才能用,例如 type myint int
)
// 定義 Vertex struct
type Vertex struct {
X, Y float64
}
// Abs method
func (v Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
func main() {
v := Vertex{3, 4}
// 使用 method 時就像別的語言使用一個 class 內ㄉ function 一樣
fmt.Println(v.Abs())
}
// v *Vertex 這樣就算下面的 v 並不是一個 pointer,go 也會幫忙轉 &v
func (v *Vertex) Scale(f float64) {
v.X = v.X * f
v.Y = v.Y * f
}
func main() {
// 如果拿掉上面 receiver 的*,也可以在這邊 &Vertex{3, 4}
v := Vertex{3, 4}
// 或是 (&v).Scale(10)
v.Scale(10)
}
Go 裡 interface 是一個型別,裡面有定義一堆 method signatures,
只要合乎這些簽章的數值(通常是 struct)就可以放進這個介面變數。
如果這個變數沒有實作規定的 method 的話,就會噴錯。
以下例子來自day15 - 介面(續)
empty interface + 以 type 為不同 case 的 switch
func main() {
printAnyType(2020)
printAnyType("Iron Man")
printAnyType(0.25)
}
// 定義一個函式,接收任何型別,並且格式化輸出值
func printAnyType(i interface{}) {
switch v := i.(type) {
case int:
fmt.Printf("case int: %d \n", v)
case string:
fmt.Printf("case string: %s \n", v)
default:
fmt.Printf("default: %v \n", v)
}
}
畢竟沒有 class,也沒有繼承的概念。
而是使用 struct 中包 struct,稱之為 composition。
go 中還能使用 embbeded,這裡不打了。
day13 - 內嵌