iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 14
1
Modern Web

從無到有,使用 Go 開發應用程式系列 第 14

Method

結構可以定義同類型的資料,而同類型的資料通常又會有同類型的行為。因為 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)) // Hi! Someone, I am Miles
}

但明顯的缺點是,它需要動態給匿名函式的值,且需要閉包才能取得 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)) // Hi! I am Miles
}

第一個傳的值就是結構變數,在函式裡就可以使用 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)) // Hi! Someone, I am Miles
}

它的概念是定義一個函式 func ,而開頭就宣告這是哪個結構所使用的,以及裡面將會用什麼變數來代表結構本身 (people People) (傳值或傳址都可以),後面就跟平常定義函數一樣。

這樣的寫法,就會把 Hello 函式跟 People 綁定在一起,用起來就會非常像物件導向的寫法了。

參考資料


上一篇
Struct
下一篇
Inheritance
系列文
從無到有,使用 Go 開發應用程式30

尚未有邦友留言

立即登入留言