結構可以定義同類型的資料,而同類型的資料通常又會有同類型的行為。因為 Go 有 Anonymous Function,有寫過 Javascript 可能第一個想到的解法是這樣:
package main
import "fmt"
type People struct { name string age int Hello func(other People) string }
func main() { var miles People
other := People{name: `Someone`} miles = People{`Miles`, 18, func(other People) string { return `Hi! ` + other.name + `, I am ` + miles.name }}
fmt.Println(miles.Hello(other)) }
|
但明顯的缺點是,它需要動態給匿名函式的值,且需要閉包才能取得 miles
變數,這樣一來函式就很難共用,二來得先宣告 miles
,才能把匿名函式指定給 miles
,整個程式會變得有點混亂。
不如,我們把函式定義改一下:
package main
import "fmt"
type People struct { name string age int Hello func(self People, other People) string }
func main() { hello := func(self People, other People) string { return `Hi! ` + other.name + `, I am ` + self.name }
other := People{name: `Someone`} miles := People{`Miles`, 18, hello}
fmt.Println(miles.Hello(miles, other)) }
|
第一個傳的值就是結構變數,在函式裡就可以使用 self 取得結構的資料。這做法有點類似 Python 定義類別裡的 self
,只是需要自己手動傳值。
事實上 Go 有提供更好的寫法:
package main
import ( "fmt" )
type People struct { name string age int }
func (people People) Hello(other People) string { return `Hi! ` + other.name + `, I am ` + people.name }
func main() { other := People{name: `Someone`} miles := People{`Miles`, 18}
fmt.Println(miles.Hello(other)) }
|
它的概念是定義一個函式 func
,而開頭就宣告這是哪個結構所使用的,以及裡面將會用什麼變數來代表結構本身 (people People)
(傳值或傳址都可以),後面就跟平常定義函數一樣。
這樣的寫法,就會把 Hello
函式跟 People
綁定在一起,用起來就會非常像物件導向的寫法了。
參考資料